blob: 4f360a66c5eee31014cf0896e5083de221d34407 [file] [log] [blame]
Monty Taylor16390e22012-11-04 22:20:36 +01001#! /usr/bin/env python
2# Copyright (C) 2011 OpenStack, LLC.
James E. Blair18e82562013-04-04 16:20:32 +00003# Copyright (c) 2012 Hewlett-Packard Development Company, L.P.
Monty Taylor16390e22012-11-04 22:20:36 +01004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
James E. Blair18e82562013-04-04 16:20:32 +000017# manage_projects.py reads a project config file called projects.yaml
18# It should look like:
19
20# - homepage: http://openstack.org
21# gerrit-host: review.openstack.org
22# local-git-dir: /var/lib/git
23# gerrit-key: /home/gerrit2/review_site/etc/ssh_host_rsa_key
Sean Dague9023a462013-05-06 06:53:10 -040024# gerrit-committer: Project Creator <openstack-infra@lists.openstack.org>
Sean Dague5906b832013-05-03 18:08:26 -040025# has-github: True
James E. Blair18e82562013-04-04 16:20:32 +000026# has-wiki: False
27# has-issues: False
28# has-downloads: False
29# acl-dir: /home/gerrit2/acls
30# acl-base: /home/gerrit2/acls/project.config
31# ---
32# - project: PROJECT_NAME
33# options:
34# - has-wiki
35# - has-issues
36# - has-downloads
37# - has-pull-requests
Monty Taylor90a630f2013-07-03 12:45:26 -070038# - track-upstream
James E. Blair18e82562013-04-04 16:20:32 +000039# homepage: Some homepage that isn't http://openstack.org
40# description: This is a great project
Monty Taylor90a630f2013-07-03 12:45:26 -070041# upstream: https://gerrit.googlesource.com/gerrit
42# upstream-prefix: upstream
James E. Blair18e82562013-04-04 16:20:32 +000043# acl-config: /path/to/gerrit/project.config
44# acl-append:
45# - /path/to/gerrit/project.config
46# acl-parameters:
47# project: OTHER_PROJECT_NAME
48
James E. Blaireab92612013-08-30 09:47:32 -070049import argparse
Monty Taylor16390e22012-11-04 22:20:36 +010050import ConfigParser
51import logging
52import os
53import re
54import shlex
55import subprocess
56import tempfile
Clark Boylan320d1502013-09-25 11:05:42 -070057import time
James E. Blair18e82562013-04-04 16:20:32 +000058import yaml
Monty Taylor16390e22012-11-04 22:20:36 +010059
Monty Taylor16390e22012-11-04 22:20:36 +010060import gerritlib.gerrit
Monty Taylor061919f2013-06-02 11:35:42 -040061import github
Monty Taylor16390e22012-11-04 22:20:36 +010062
Clark Boylanda402e52012-12-04 15:23:43 -080063import jeepyb.gerritdb
64
Monty Taylor16390e22012-11-04 22:20:36 +010065log = logging.getLogger("manage_projects")
66
67
68def run_command(cmd, status=False, env={}):
69 cmd_list = shlex.split(str(cmd))
70 newenv = os.environ
71 newenv.update(env)
72 log.debug("Executing command: %s" % " ".join(cmd_list))
73 p = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
74 stderr=subprocess.STDOUT, env=newenv)
75 (out, nothing) = p.communicate()
76 log.debug("Return code: %s" % p.returncode)
77 log.debug("Command said: %s" % out.strip())
78 if status:
79 return (p.returncode, out.strip())
80 return out.strip()
81
82
83def run_command_status(cmd, env={}):
84 return run_command(cmd, True, env)
85
86
87def git_command(repo_dir, sub_cmd, env={}):
88 git_dir = os.path.join(repo_dir, '.git')
89 cmd = "git --git-dir=%s --work-tree=%s %s" % (git_dir, repo_dir, sub_cmd)
90 status, _ = run_command(cmd, True, env)
91 return status
92
93
Clark Boylan808b5132012-11-14 15:52:02 -080094def git_command_output(repo_dir, sub_cmd, env={}):
95 git_dir = os.path.join(repo_dir, '.git')
96 cmd = "git --git-dir=%s --work-tree=%s %s" % (git_dir, repo_dir, sub_cmd)
97 status, out = run_command(cmd, True, env)
98 return (status, out)
99
100
Monty Taylor863a6712013-03-03 09:52:36 -0500101def write_acl_config(project, acl_dir, acl_base, acl_append, parameters):
102 project_parts = os.path.split(project)
103 if len(project_parts) > 1:
104 repo_base = os.path.join(acl_dir, *project_parts[:-1])
105 if not os.path.exists(repo_base):
James E. Blair22e1c692013-03-14 11:40:37 -0700106 os.makedirs(repo_base)
Monty Taylor863a6712013-03-03 09:52:36 -0500107 if not os.path.isdir(repo_base):
108 return 1
Monty Taylore8bb6e42013-03-08 15:01:56 -0500109 project = project_parts[-1]
110 config_file = os.path.join(repo_base, "%s.config" % project)
Monty Taylor863a6712013-03-03 09:52:36 -0500111 else:
112 config_file = os.path.join(acl_dir, "%s.config" % project)
James E. Blair18e82562013-04-04 16:20:32 +0000113 if 'project' not in parameters:
114 parameters['project'] = project
Monty Taylor863a6712013-03-03 09:52:36 -0500115 with open(config_file, 'w') as config:
116 if acl_base and os.path.exists(acl_base):
117 config.write(open(acl_base, 'r').read())
118 for acl_snippet in acl_append:
119 if not os.path.exists(acl_snippet):
120 acl_snippet = os.path.join(acl_dir, acl_snippet)
121 if not os.path.exists(acl_snippet):
122 continue
123 with open(acl_snippet, 'r') as append_content:
124 config.write(append_content.read() % parameters)
125
126
Monty Taylor16390e22012-11-04 22:20:36 +0100127def fetch_config(project, remote_url, repo_path, env={}):
128 status = git_command(repo_path, "fetch %s +refs/meta/config:"
129 "refs/remotes/gerrit-meta/config" % remote_url, env)
130 if status != 0:
Clark Boylan796eada2013-09-25 10:51:35 -0700131 log.error("Failed to fetch refs/meta/config for project: %s" % project)
Monty Taylor16390e22012-11-04 22:20:36 +0100132 return False
133 # Because the following fails if executed more than once you should only
134 # run fetch_config once in each repo.
Monty Taylor71262092013-10-12 20:47:21 -0400135 status = git_command(repo_path, "checkout -B config "
Monty Taylor16390e22012-11-04 22:20:36 +0100136 "remotes/gerrit-meta/config")
137 if status != 0:
Clark Boylan796eada2013-09-25 10:51:35 -0700138 log.error("Failed to checkout config for project: %s" % project)
Monty Taylor16390e22012-11-04 22:20:36 +0100139 return False
140
141 return True
142
143
144def copy_acl_config(project, repo_path, acl_config):
145 if not os.path.exists(acl_config):
146 return False
147
148 acl_dest = os.path.join(repo_path, "project.config")
149 status, _ = run_command("cp %s %s" %
150 (acl_config, acl_dest), status=True)
151 if status == 0:
Clark Boylan333f4cb2013-04-04 16:55:01 -0700152 status = git_command(repo_path, "diff --quiet")
Monty Taylor16390e22012-11-04 22:20:36 +0100153 if status != 0:
154 return True
155 return False
156
157
Sean Dague9023a462013-05-06 06:53:10 -0400158def push_acl_config(project, remote_url, repo_path, gitid, env={}):
159 cmd = "commit -a -m'Update project config.' --author='%s'" % gitid
Monty Taylor16390e22012-11-04 22:20:36 +0100160 status = git_command(repo_path, cmd)
161 if status != 0:
Clark Boylan796eada2013-09-25 10:51:35 -0700162 log.error("Failed to commit config for project: %s" % project)
Monty Taylor16390e22012-11-04 22:20:36 +0100163 return False
Clark Boylan808b5132012-11-14 15:52:02 -0800164 status, out = git_command_output(repo_path,
Monty Taylorda3bada2012-11-22 09:38:22 -0800165 "push %s HEAD:refs/meta/config" %
166 remote_url, env)
Monty Taylor16390e22012-11-04 22:20:36 +0100167 if status != 0:
Clark Boylan796eada2013-09-25 10:51:35 -0700168 log.error("Failed to push config for project: %s" % project)
Monty Taylor16390e22012-11-04 22:20:36 +0100169 return False
170 return True
171
172
Clark Boylan320d1502013-09-25 11:05:42 -0700173def _get_group_uuid(group):
Clark Boylanda402e52012-12-04 15:23:43 -0800174 cursor = jeepyb.gerritdb.connect().cursor()
175 query = "SELECT group_uuid FROM account_groups WHERE name = %s"
176 cursor.execute(query, group)
177 data = cursor.fetchone()
Monty Taylor16390e22012-11-04 22:20:36 +0100178 if data:
Clark Boylanda402e52012-12-04 15:23:43 -0800179 return data[0]
Monty Taylor16390e22012-11-04 22:20:36 +0100180 return None
181
182
Clark Boylan320d1502013-09-25 11:05:42 -0700183def _wait_for_group(gerrit, group):
184 """Wait for up to 10 seconds for the group to be created."""
185 for x in range(10):
186 groups = gerrit.listGroups()
187 if group in groups:
188 break
189 time.sleep(1)
190
191
Monty Taylor16390e22012-11-04 22:20:36 +0100192def get_group_uuid(gerrit, group):
Clark Boylan320d1502013-09-25 11:05:42 -0700193 uuid = _get_group_uuid(group)
Monty Taylor16390e22012-11-04 22:20:36 +0100194 if uuid:
195 return uuid
Clark Boylan68ce3292013-07-01 11:45:46 -0700196 gerrit.createGroup(group)
Clark Boylan320d1502013-09-25 11:05:42 -0700197 _wait_for_group(gerrit, group)
198 uuid = _get_group_uuid(group)
Monty Taylor16390e22012-11-04 22:20:36 +0100199 if uuid:
200 return uuid
201 return None
202
203
204def create_groups_file(project, gerrit, repo_path):
205 acl_config = os.path.join(repo_path, "project.config")
206 group_file = os.path.join(repo_path, "groups")
207 uuids = {}
208 for line in open(acl_config, 'r'):
Clark Boylan5c9670f2012-11-14 17:48:55 -0800209 r = re.match(r'^\s+.*group\s+(.*)$', line)
Monty Taylor16390e22012-11-04 22:20:36 +0100210 if r:
211 group = r.group(1)
212 if group in uuids.keys():
213 continue
214 uuid = get_group_uuid(gerrit, group)
215 if uuid:
216 uuids[group] = uuid
217 else:
Clark Boylan796eada2013-09-25 10:51:35 -0700218 log.error("Unable to get UUID for group %s." % group)
Monty Taylor16390e22012-11-04 22:20:36 +0100219 return False
220 if uuids:
221 with open(group_file, 'w') as fp:
222 for group, uuid in uuids.items():
223 fp.write("%s\t%s\n" % (uuid, group))
224 status = git_command(repo_path, "add groups")
225 if status != 0:
Clark Boylan796eada2013-09-25 10:51:35 -0700226 log.error("Failed to add groups file for project: %s" % project)
Monty Taylor16390e22012-11-04 22:20:36 +0100227 return False
228 return True
229
230
231def make_ssh_wrapper(gerrit_user, gerrit_key):
232 (fd, name) = tempfile.mkstemp(text=True)
233 os.write(fd, '#!/bin/bash\n')
234 os.write(fd,
235 'ssh -i %s -l %s -o "StrictHostKeyChecking no" $@\n' %
236 (gerrit_key, gerrit_user))
237 os.close(fd)
Sergey Lukjanovdb8e7072013-07-22 12:13:35 +0400238 os.chmod(name, 0o755)
Monty Taylor16390e22012-11-04 22:20:36 +0100239 return dict(GIT_SSH=name)
240
241
Sean Dague5906b832013-05-03 18:08:26 -0400242def create_github_project(defaults, options, project, description, homepage):
James E. Blair18e82562013-04-04 16:20:32 +0000243 default_has_issues = defaults.get('has-issues', False)
244 default_has_downloads = defaults.get('has-downloads', False)
245 default_has_wiki = defaults.get('has-wiki', False)
Sean Dague5906b832013-05-03 18:08:26 -0400246 has_issues = 'has-issues' in options or default_has_issues
247 has_downloads = 'has-downloads' in options or default_has_downloads
248 has_wiki = 'has-wiki' in options or default_has_wiki
Monty Taylor16390e22012-11-04 22:20:36 +0100249
James E. Blair18e82562013-04-04 16:20:32 +0000250 GITHUB_SECURE_CONFIG = defaults.get(
251 'github-config',
252 '/etc/github/github-projects.secure.config')
253
Monty Taylorda3bada2012-11-22 09:38:22 -0800254 secure_config = ConfigParser.ConfigParser()
255 secure_config.read(GITHUB_SECURE_CONFIG)
Monty Taylor16390e22012-11-04 22:20:36 +0100256
Monty Taylorda3bada2012-11-22 09:38:22 -0800257 # Project creation doesn't work via oauth
258 ghub = github.Github(secure_config.get("github", "username"),
259 secure_config.get("github", "password"))
260 orgs = ghub.get_user().get_orgs()
261 orgs_dict = dict(zip([o.login.lower() for o in orgs], orgs))
Monty Taylor16390e22012-11-04 22:20:36 +0100262
Sean Dague5906b832013-05-03 18:08:26 -0400263 # Find the project's repo
264 project_split = project.split('/', 1)
265 org_name = project_split[0]
266 if len(project_split) > 1:
267 repo_name = project_split[1]
268 else:
269 repo_name = project
270
271 try:
272 org = orgs_dict[org_name.lower()]
273 except KeyError:
274 # We do not have control of this github org ignore the project.
Sean Dague433783d2013-05-04 07:47:08 -0400275 return
Sean Dague5906b832013-05-03 18:08:26 -0400276 try:
277 repo = org.get_repo(repo_name)
278 except github.GithubException:
279 repo = org.create_repo(repo_name,
280 homepage=homepage,
281 has_issues=has_issues,
282 has_downloads=has_downloads,
283 has_wiki=has_wiki)
284 if description:
285 repo.edit(repo_name, description=description)
286 if homepage:
287 repo.edit(repo_name, homepage=homepage)
288
289 repo.edit(repo_name, has_issues=has_issues,
290 has_downloads=has_downloads,
291 has_wiki=has_wiki)
292
293 if 'gerrit' not in [team.name for team in repo.get_teams()]:
294 teams = org.get_teams()
295 teams_dict = dict(zip([t.name.lower() for t in teams], teams))
296 teams_dict['gerrit'].add_to_repos(repo)
297
298
Monty Taylor90a630f2013-07-03 12:45:26 -0700299# TODO(mordred): Inspect repo_dir:master for a description
300# override
301def find_description_override(repo_path):
302 return None
303
304
Sean Dague5906b832013-05-03 18:08:26 -0400305def main():
James E. Blaireab92612013-08-30 09:47:32 -0700306 parser = argparse.ArgumentParser(description='Manage projects')
307 parser.add_argument('-v', dest='verbose', action='store_true',
308 help='verbose output')
309 parser.add_argument('--nocleanup', action='store_true',
310 help='do not remove temp directories')
311 parser.add_argument('projects', metavar='project', nargs='*',
312 help='name of project(s) to process')
313 args = parser.parse_args()
314
315 if args.verbose:
316 logging.basicConfig(level=logging.DEBUG)
317 else:
318 logging.basicConfig(level=logging.ERROR)
Sean Dague5906b832013-05-03 18:08:26 -0400319
320 PROJECTS_YAML = os.environ.get('PROJECTS_YAML',
321 '/home/gerrit2/projects.yaml')
322 configs = [config for config in yaml.load_all(open(PROJECTS_YAML))]
323 defaults = configs[0][0]
324 default_has_github = defaults.get('has-github', True)
325
326 LOCAL_GIT_DIR = defaults.get('local-git-dir', '/var/lib/git')
Monty Taylor90a630f2013-07-03 12:45:26 -0700327 JEEPYB_CACHE_DIR = defaults.get('jeepyb-cache-dir', '/var/lib/jeepyb')
Sean Dague5906b832013-05-03 18:08:26 -0400328 ACL_DIR = defaults.get('acl-dir')
329 GERRIT_HOST = defaults.get('gerrit-host')
Jay Pipesa8068d32013-06-22 20:33:41 -0400330 GERRIT_PORT = int(defaults.get('gerrit-port', '29418'))
Sean Dague5906b832013-05-03 18:08:26 -0400331 GERRIT_USER = defaults.get('gerrit-user')
332 GERRIT_KEY = defaults.get('gerrit-key')
Sean Dague9023a462013-05-06 06:53:10 -0400333 GERRIT_GITID = defaults.get('gerrit-committer')
Jay Pipes2f13d562013-06-16 12:01:09 -0400334 GERRIT_SYSTEM_USER = defaults.get('gerrit-system-user', 'gerrit2')
335 GERRIT_SYSTEM_GROUP = defaults.get('gerrit-system-group', 'gerrit2')
Sean Dague5906b832013-05-03 18:08:26 -0400336
Monty Taylorda3bada2012-11-22 09:38:22 -0800337 gerrit = gerritlib.gerrit.Gerrit('localhost',
338 GERRIT_USER,
Monty Taylor805a3012013-06-21 02:32:08 -0400339 GERRIT_PORT,
Monty Taylorda3bada2012-11-22 09:38:22 -0800340 GERRIT_KEY)
341 project_list = gerrit.listProjects()
342 ssh_env = make_ssh_wrapper(GERRIT_USER, GERRIT_KEY)
343 try:
Monty Taylor16390e22012-11-04 22:20:36 +0100344
James E. Blair18e82562013-04-04 16:20:32 +0000345 for section in configs[1]:
346 project = section['project']
James E. Blaireab92612013-08-30 09:47:32 -0700347 if args.projects and project not in args.projects:
348 continue
James E. Blair18e82562013-04-04 16:20:32 +0000349 options = section.get('options', dict())
350 description = section.get('description', None)
351 homepage = section.get('homepage', defaults.get('homepage', None))
352 upstream = section.get('upstream', None)
Monty Taylor90a630f2013-07-03 12:45:26 -0700353 upstream_prefix = section.get('upstream-prefix', None)
354 track_upstream = 'track-upstream' in options
James E. Blair18e82562013-04-04 16:20:32 +0000355
Monty Taylorda3bada2012-11-22 09:38:22 -0800356 project_git = "%s.git" % project
Monty Taylor90a630f2013-07-03 12:45:26 -0700357 remote_url = "ssh://localhost:%s/%s" % (GERRIT_PORT, project)
358
Jeremy Stanleyd211fa52013-10-16 19:34:07 +0000359 # Create the project in Gerrit first, since it will fail
360 # spectacularly if its project directory or local replica
361 # already exist on disk
362 project_created = False
363 if project not in project_list:
364 try:
365 gerrit.createProject(project)
366 project_created = True
367 except Exception:
368 log.exception(
369 "Exception creating %s in Gerrit." % project)
370
Monty Taylor90a630f2013-07-03 12:45:26 -0700371 # Create the repo for the local git mirror
372 git_mirror_path = os.path.join(LOCAL_GIT_DIR, project_git)
373 if not os.path.exists(git_mirror_path):
374 run_command("git --bare init %s" % git_mirror_path)
375 run_command("chown -R %s:%s %s"
376 % (GERRIT_SYSTEM_USER, GERRIT_SYSTEM_GROUP,
377 git_mirror_path))
378
379 # Start processing the local JEEPYB cache
380 repo_path = os.path.join(JEEPYB_CACHE_DIR, project)
381 git_opts = dict(upstream=upstream,
382 repo_path=repo_path,
383 remote_url=remote_url)
384
385 # If we don't have a local copy already, get one
Jeremy Stanleyd211fa52013-10-16 19:34:07 +0000386 if not os.path.exists(repo_path) or project_created:
Monty Taylor90a630f2013-07-03 12:45:26 -0700387 if not os.path.exists(os.path.dirname(repo_path)):
388 os.makedirs(os.path.dirname(repo_path))
389 # Three choices
390 # - If gerrit has it, get from gerrit
391 # - If gerrit doesn't have it:
392 # - If it has an upstream, clone that
393 # - If it doesn't, create it
394
395 # Gerrit knows about the project, clone it
396 if project in project_list:
397 run_command(
398 "git clone %(remote_url)s %(repo_path)s" % git_opts,
399 env=ssh_env)
400 if upstream:
401 git_command(
402 repo_path,
403 "remote add -f upstream %(upstream)s" % git_opts)
404
405 # Gerrit doesn't have it, but it has an upstream configured
406 # We're probably importing it for the first time, clone
407 # upstream, but then ongoing we want gerrit to ge origin
408 # and upstream to be only there for ongoing tracking
409 # purposes, so rename origin to upstream and add a new
410 # origin remote that points at gerrit
411 elif upstream:
412 run_command(
413 "git clone %(upstream)s %(repo_path)s" % git_opts,
414 env=ssh_env)
415 git_command(
416 repo_path,
417 "fetch origin +refs/heads/*:refs/copy/heads/*",
418 env=ssh_env)
419 git_command(repo_path, "remote rename origin upstream")
420 git_command(
421 repo_path,
422 "remote add origin %(remote_url)s" % git_opts)
423 push_string = "push %s +refs/copy/heads/*:refs/heads/*"
424
425 # Neither gerrit has it, nor does it have an upstream,
426 # just create a whole new one
427 else:
428 run_command("git init %s" % repo_path)
429 git_command(
430 repo_path,
Monty Taylorf5b11182013-10-18 19:32:03 -0400431 "remote add origin %(remote_url)s" % git_opts)
Monty Taylor90a630f2013-07-03 12:45:26 -0700432 with open(os.path.join(repo_path,
433 ".gitreview"),
434 'w') as gitreview:
435 gitreview.write("""[gerrit]
436host=%s
437port=%s
438project=%s
439""" % (GERRIT_HOST, GERRIT_PORT, project_git))
440 git_command(repo_path, "add .gitreview")
441 cmd = ("commit -a -m'Added .gitreview' --author='%s'"
442 % GERRIT_GITID)
443 git_command(repo_path, cmd)
444 push_string = "push %s HEAD:refs/heads/master"
445
446 # We do have a local copy of it already, make sure it's
447 # in shape to have work done.
448 else:
449 if project in project_list:
450
451 # If we're configured to track upstream but the repo
452 # does not have an upstream remote, add one
453 if (track_upstream and
454 'upstream' not in git_command_output(
455 repo_path, 'remote')[1]):
456 git_command(
457 repo_path,
458 "remote add upstream %(upstream)s" % git_opts)
459
460 # If we're configured to track upstream, make sure that
461 # the upstream URL matches the config
462 else:
463 git_command(
464 repo_path,
465 "remote set-url upstream %(upstream)s" % git_opts)
466
467 # Now that we have any upstreams configured, fetch all
468 # of the refs we might need, pruning remote branches
469 # that no longer exist
470 git_command(
471 repo_path, "remote update --prune", env=ssh_env)
472
473 # TODO(mordred): This is here so that later we can
474 # inspect the master branch for meta-info
475 # Checkout master and reset to the state of origin/master
476 git_command(repo_path, "checkout -B master origin/master")
477
478 description = find_description_override(repo_path) or description
Monty Taylor16390e22012-11-04 22:20:36 +0100479
Sean Dague5906b832013-05-03 18:08:26 -0400480 if 'has-github' in options or default_has_github:
481 create_github_project(defaults, options, project,
482 description, homepage)
Monty Taylorda3bada2012-11-22 09:38:22 -0800483
Jeremy Stanleyd211fa52013-10-16 19:34:07 +0000484 if project_created:
Monty Taylorda3bada2012-11-22 09:38:22 -0800485 try:
Monty Taylorda3bada2012-11-22 09:38:22 -0800486 git_command(repo_path,
Clark Boylane0c725b2012-11-30 15:15:55 -0800487 push_string % remote_url,
Monty Taylorda3bada2012-11-22 09:38:22 -0800488 env=ssh_env)
489 git_command(repo_path,
490 "push --tags %s" % remote_url, env=ssh_env)
Clark Boylan796eada2013-09-25 10:51:35 -0700491 except Exception:
492 log.exception(
Jeremy Stanleyd211fa52013-10-16 19:34:07 +0000493 "Error pushing %s to Gerrit." % project)
Monty Taylor90a630f2013-07-03 12:45:26 -0700494
495 # If we're configured to track upstream, make sure we have
496 # upstream's refs, and then push them to the appropriate
497 # branches in gerrit
498 if track_upstream:
499 git_command(
500 repo_path,
501 "remote update upstream --prune", env=ssh_env)
502 # Any branch that exists in the upstream remote, we want
503 # a local branch of, optionally prefixed with the
504 # upstream prefix value
505 for branch in git_command_output(
506 repo_path, "branch -a")[1].split():
507 if not branch.strip().startswith("remotes/upstream"):
508 continue
509 if "->" in branch:
510 continue
511 local_branch = branch[len('remotes/upstream/'):]
512 if upstream_prefix:
513 local_branch = "%s/%s" % (
514 upstream_prefix, local_branch)
515
516 # Check out an up to date copy of the branch, so that
517 # we can push it and it will get picked up below
518 git_command(repo_path, "checkout -B %s %s" % (
519 local_branch, branch))
520
521 try:
522 # Push all of the local branches to similarly named
523 # Branches on gerrit. Also, push all of the tags
524 git_command(
525 repo_path,
Monty Taylora54b0af2013-10-15 13:42:59 -0300526 "push origin refs/heads/*:refs/heads/*",
Monty Taylor90a630f2013-07-03 12:45:26 -0700527 env=ssh_env)
Monty Taylore5c1eed2013-10-23 08:55:13 -0500528 git_command(repo_path, 'push origin --tags', env=ssh_env)
Monty Taylor90a630f2013-07-03 12:45:26 -0700529 except Exception:
530 log.exception(
531 "Error pushing %s to Gerrit." % project)
Monty Taylorda3bada2012-11-22 09:38:22 -0800532
Jeremy Stanley8b9f93f2013-01-21 02:44:21 +0000533 try:
James E. Blair18e82562013-04-04 16:20:32 +0000534 acl_config = section.get('acl-config',
535 '%s.config' % os.path.join(ACL_DIR,
536 project))
537 except AttributeError:
538 acl_config = None
539
540 if acl_config:
541 if not os.path.isfile(acl_config):
542 write_acl_config(project,
543 ACL_DIR,
544 section.get('acl-base', None),
545 section.get('acl-append', []),
546 section.get('acl-parameters', {}))
James E. Blair18e82562013-04-04 16:20:32 +0000547 try:
James E. Blair18e82562013-04-04 16:20:32 +0000548 if (fetch_config(project,
549 remote_url,
550 repo_path,
551 ssh_env) and
552 copy_acl_config(project, repo_path,
553 acl_config) and
554 create_groups_file(project, gerrit, repo_path)):
555 push_acl_config(project,
556 remote_url,
557 repo_path,
Sean Dague9023a462013-05-06 06:53:10 -0400558 GERRIT_GITID,
James E. Blair18e82562013-04-04 16:20:32 +0000559 ssh_env)
Clark Boylan796eada2013-09-25 10:51:35 -0700560 except Exception:
561 log.exception(
562 "Exception processing ACLS for %s." % project)
James E. Blair18e82562013-04-04 16:20:32 +0000563 finally:
Monty Taylorf8b2b622013-10-12 20:51:25 -0400564 git_command(repo_path, 'reset --hard')
Monty Taylor90a630f2013-07-03 12:45:26 -0700565 git_command(repo_path, 'checkout master')
566 git_command(repo_path, 'branch -D config')
567
Monty Taylorda3bada2012-11-22 09:38:22 -0800568 finally:
569 os.unlink(ssh_env['GIT_SSH'])
Jeremy Stanley06efb062013-04-15 20:18:16 +0000570
571if __name__ == "__main__":
572 main()