summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2015-09-08 13:27:20 -0700
committerDan Willemsen <dwillemsen@google.com>2015-09-09 12:35:56 -0700
commit250303b437855c2b50d052a05a08ed517423af8b (patch)
treeae9df65083e7e0e53d3438adb752cad2dbe27cb5
parentba72d8301e33344b3b11e286619c99568c37db1a (diff)
downloadgit-repo-250303b437855c2b50d052a05a08ed517423af8b.tar.gz
GITC: Always update the gitc manifest from the repo manifest
This way any changes made to the main manifest are reflected in the gitc manifest. It's also necessary to use both manifests to sync since the information required to update the gitc manifest is actually in the repo manifest. This also fixes a few issues that came up when testing. notdefault groups weren't being saved to the gitc manifest in a method that matched 'sync'. The merge branch wasn't always being set to the correct value either. Change-Id: I5dbc850dd73a9fbd10ab2470ae4c40e46ff894de
-rw-r--r--gitc_utils.py85
-rw-r--r--manifest_xml.py5
-rw-r--r--subcmds/gitc_init.py8
-rw-r--r--subcmds/start.py10
-rw-r--r--subcmds/sync.py26
5 files changed, 100 insertions, 34 deletions
diff --git a/gitc_utils.py b/gitc_utils.py
index d082c8d7..04307a3c 100644
--- a/gitc_utils.py
+++ b/gitc_utils.py
@@ -15,6 +15,8 @@
15 15
16from __future__ import print_function 16from __future__ import print_function
17import os 17import os
18import platform
19import re
18import sys 20import sys
19import time 21import time
20 22
@@ -22,6 +24,7 @@ import git_command
22import git_config 24import git_config
23import wrapper 25import wrapper
24 26
27from manifest_xml import GitcManifest
25 28
26GITC_FS_ROOT_DIR = '/gitc/manifest-rw/' 29GITC_FS_ROOT_DIR = '/gitc/manifest-rw/'
27NUM_BATCH_RETRIEVE_REVISIONID = 300 30NUM_BATCH_RETRIEVE_REVISIONID = 300
@@ -65,26 +68,86 @@ def _set_project_revisions(projects):
65 sys.exit(1) 68 sys.exit(1)
66 proj.revisionExpr = gitcmd.stdout.split('\t')[0] 69 proj.revisionExpr = gitcmd.stdout.split('\t')[0]
67 70
68def generate_gitc_manifest(client_dir, manifest, projects=None): 71def _manifest_groups(manifest):
72 """Returns the manifest group string that should be synced
73
74 This is the same logic used by Command.GetProjects(), which is used during
75 repo sync
76
77 @param manifest: The XmlManifest object
78 """
79 mp = manifest.manifestProject
80 groups = mp.config.GetString('manifest.groups')
81 if not groups:
82 groups = 'default,platform-' + platform.system().lower()
83 return groups
84
85def generate_gitc_manifest(repodir, client_name, gitc_manifest, repo_manifest_file, paths=None):
69 """Generate a manifest for shafsd to use for this GITC client. 86 """Generate a manifest for shafsd to use for this GITC client.
70 87
71 @param client_dir: GITC client directory to install the .manifest file in. 88 @param repodir: The repo directory
72 @param manifest: XmlManifest object representing the repo manifest. 89 @param client_name: The gitc client name
73 @param projects: List of projects we want to update, this must be a sublist 90 @param gitc_manifest: Current gitc manifest, or None if there isn't one yet
74 of manifest.projects to work properly. If not provided, 91 @param repo_manifest_file: The file used by the main repo manifest
75 manifest.projects is used. 92 @param paths: List of project paths we want to update.
76 """ 93 """
94 manifest = GitcManifest(repodir, client_name)
95 manifest.Override(repo_manifest_file)
96
77 print('Generating GITC Manifest by fetching revision SHAs for each ' 97 print('Generating GITC Manifest by fetching revision SHAs for each '
78 'project.') 98 'project.')
79 if projects is None: 99 if paths is None:
80 projects = manifest.projects 100 paths = manifest.paths.keys()
101
102 groups = [x for x in re.split(r'[,\s]+', _manifest_groups(manifest)) if x]
103
104 # Convert the paths to projects, and filter them to the matched groups.
105 projects = [manifest.paths[p] for p in paths]
106 projects = [p for p in projects if p.MatchesGroups(groups)]
107
108 if gitc_manifest is not None:
109 for path, proj in manifest.paths.iteritems():
110 if not proj.MatchesGroups(groups):
111 continue
112
113 if not proj.upstream and not git_config.IsId(proj.revisionExpr):
114 proj.upstream = proj.revisionExpr
115
116 if not path in gitc_manifest.paths:
117 # Any new projects need their first revision, even if we weren't asked
118 # for them.
119 projects.append(proj)
120 elif not path in paths:
121 # And copy revisions from the previous manifest if we're not updating
122 # them now.
123 gitc_proj = gitc_manifest.paths[path]
124 if gitc_proj.old_revision:
125 proj.revisionExpr = None
126 proj.old_revision = gitc_proj.old_revision
127 else:
128 proj.revisionExpr = gitc_proj.revisionExpr
129
81 index = 0 130 index = 0
82 while index < len(projects): 131 while index < len(projects):
83 _set_project_revisions( 132 _set_project_revisions(
84 projects[index:(index+NUM_BATCH_RETRIEVE_REVISIONID)]) 133 projects[index:(index+NUM_BATCH_RETRIEVE_REVISIONID)])
85 index += NUM_BATCH_RETRIEVE_REVISIONID 134 index += NUM_BATCH_RETRIEVE_REVISIONID
135
136 if gitc_manifest is not None:
137 for path, proj in gitc_manifest.paths.iteritems():
138 if proj.old_revision and path in paths:
139 # If we updated a project that has been started, keep the old-revision
140 # updated.
141 repo_proj = manifest.paths[path]
142 repo_proj.old_revision = repo_proj.revisionExpr
143 repo_proj.revisionExpr = None
144
145 # Convert URLs from relative to absolute.
146 for name, remote in manifest.remotes.iteritems():
147 remote.fetchUrl = remote.resolvedFetchUrl
148
86 # Save the manifest. 149 # Save the manifest.
87 save_manifest(manifest, client_dir=client_dir) 150 save_manifest(manifest)
88 151
89def save_manifest(manifest, client_dir=None): 152def save_manifest(manifest, client_dir=None):
90 """Save the manifest file in the client_dir. 153 """Save the manifest file in the client_dir.
@@ -95,7 +158,7 @@ def save_manifest(manifest, client_dir=None):
95 if not client_dir: 158 if not client_dir:
96 client_dir = manifest.gitc_client_dir 159 client_dir = manifest.gitc_client_dir
97 with open(os.path.join(client_dir, '.manifest'), 'w') as f: 160 with open(os.path.join(client_dir, '.manifest'), 'w') as f:
98 manifest.Save(f) 161 manifest.Save(f, groups=_manifest_groups(manifest))
99 # TODO(sbasi/jorg): Come up with a solution to remove the sleep below. 162 # TODO(sbasi/jorg): Come up with a solution to remove the sleep below.
100 # Give the GITC filesystem time to register the manifest changes. 163 # Give the GITC filesystem time to register the manifest changes.
101 time.sleep(3) \ No newline at end of file 164 time.sleep(3)
diff --git a/manifest_xml.py b/manifest_xml.py
index a7fe8ddf..3ac607ec 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -167,12 +167,13 @@ class XmlManifest(object):
167 def _ParseGroups(self, groups): 167 def _ParseGroups(self, groups):
168 return [x for x in re.split(r'[,\s]+', groups) if x] 168 return [x for x in re.split(r'[,\s]+', groups) if x]
169 169
170 def Save(self, fd, peg_rev=False, peg_rev_upstream=True): 170 def Save(self, fd, peg_rev=False, peg_rev_upstream=True, groups=None):
171 """Write the current manifest out to the given file descriptor. 171 """Write the current manifest out to the given file descriptor.
172 """ 172 """
173 mp = self.manifestProject 173 mp = self.manifestProject
174 174
175 groups = mp.config.GetString('manifest.groups') 175 if groups is None:
176 groups = mp.config.GetString('manifest.groups')
176 if groups: 177 if groups:
177 groups = self._ParseGroups(groups) 178 groups = self._ParseGroups(groups)
178 179
diff --git a/subcmds/gitc_init.py b/subcmds/gitc_init.py
index e99affa5..c957a9dc 100644
--- a/subcmds/gitc_init.py
+++ b/subcmds/gitc_init.py
@@ -68,15 +68,13 @@ use for this GITC client.
68 os.mkdir(self.client_dir) 68 os.mkdir(self.client_dir)
69 super(GitcInit, self).Execute(opt, args) 69 super(GitcInit, self).Execute(opt, args)
70 70
71 for name, remote in self.manifest.remotes.iteritems(): 71 manifest_file = self.manifest.manifestFile
72 remote.fetchUrl = remote.resolvedFetchUrl
73
74 if opt.manifest_file: 72 if opt.manifest_file:
75 if not os.path.exists(opt.manifest_file): 73 if not os.path.exists(opt.manifest_file):
76 print('fatal: Specified manifest file %s does not exist.' % 74 print('fatal: Specified manifest file %s does not exist.' %
77 opt.manifest_file) 75 opt.manifest_file)
78 sys.exit(1) 76 sys.exit(1)
79 self.manifest.Override(opt.manifest_file) 77 manifest_file = opt.manifest_file
80 gitc_utils.generate_gitc_manifest(self.client_dir, self.manifest) 78 gitc_utils.generate_gitc_manifest(self.repodir, opt.gitc_client, None, manifest_file)
81 print('Please run `cd %s` to view your GITC client.' % 79 print('Please run `cd %s` to view your GITC client.' %
82 os.path.join(gitc_utils.GITC_FS_ROOT_DIR, opt.gitc_client)) 80 os.path.join(gitc_utils.GITC_FS_ROOT_DIR, opt.gitc_client))
diff --git a/subcmds/start.py b/subcmds/start.py
index 188fd7c6..940c3413 100644
--- a/subcmds/start.py
+++ b/subcmds/start.py
@@ -57,7 +57,6 @@ revision specified in the manifest.
57 print("error: at least one project must be specified", file=sys.stderr) 57 print("error: at least one project must be specified", file=sys.stderr)
58 sys.exit(1) 58 sys.exit(1)
59 59
60 proj_name_to_gitc_proj_dict = {}
61 if self.gitc_manifest: 60 if self.gitc_manifest:
62 all_projects = self.GetProjects(projects, manifest=self.gitc_manifest, 61 all_projects = self.GetProjects(projects, manifest=self.gitc_manifest,
63 missing_ok=True) 62 missing_ok=True)
@@ -67,7 +66,6 @@ revision specified in the manifest.
67 else: 66 else:
68 project.already_synced = False 67 project.already_synced = False
69 project.old_revision = project.revisionExpr 68 project.old_revision = project.revisionExpr
70 proj_name_to_gitc_proj_dict[project.name] = project
71 project.revisionExpr = None 69 project.revisionExpr = None
72 # Save the GITC manifest. 70 # Save the GITC manifest.
73 gitc_utils.save_manifest(self.gitc_manifest) 71 gitc_utils.save_manifest(self.gitc_manifest)
@@ -77,9 +75,10 @@ revision specified in the manifest.
77 pm = Progress('Starting %s' % nb, len(all_projects)) 75 pm = Progress('Starting %s' % nb, len(all_projects))
78 for project in all_projects: 76 for project in all_projects:
79 pm.update() 77 pm.update()
78
80 if self.gitc_manifest: 79 if self.gitc_manifest:
81 gitc_project = proj_name_to_gitc_proj_dict[project.name] 80 gitc_project = self.gitc_manifest.paths[project.relpath]
82 # Sync projects that have already been opened. 81 # Sync projects that have not been opened.
83 if not gitc_project.already_synced: 82 if not gitc_project.already_synced:
84 proj_localdir = os.path.join(self.gitc_manifest.gitc_client_dir, 83 proj_localdir = os.path.join(self.gitc_manifest.gitc_client_dir,
85 project.relpath) 84 project.relpath)
@@ -89,7 +88,7 @@ revision specified in the manifest.
89 project.Sync_NetworkHalf() 88 project.Sync_NetworkHalf()
90 sync_buf = SyncBuffer(self.manifest.manifestProject.config) 89 sync_buf = SyncBuffer(self.manifest.manifestProject.config)
91 project.Sync_LocalHalf(sync_buf) 90 project.Sync_LocalHalf(sync_buf)
92 project.revisionExpr = gitc_project.old_revision 91 project.revisionId = gitc_project.old_revision
93 92
94 # If the current revision is a specific SHA1 then we can't push back 93 # If the current revision is a specific SHA1 then we can't push back
95 # to it; so substitute with dest_branch if defined, or with manifest 94 # to it; so substitute with dest_branch if defined, or with manifest
@@ -100,6 +99,7 @@ revision specified in the manifest.
100 branch_merge = project.dest_branch 99 branch_merge = project.dest_branch
101 else: 100 else:
102 branch_merge = self.manifest.default.revisionExpr 101 branch_merge = self.manifest.default.revisionExpr
102
103 if not project.StartBranch(nb, branch_merge=branch_merge): 103 if not project.StartBranch(nb, branch_merge=branch_merge):
104 err.append(project) 104 err.append(project)
105 pm.end() 105 pm.end()
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 7b44dbd8..79cfaaa5 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -670,32 +670,36 @@ later is required to fix a server side protocol bug.
670 if opt.jobs is None: 670 if opt.jobs is None:
671 self.jobs = self.manifest.default.sync_j 671 self.jobs = self.manifest.default.sync_j
672 672
673 # TODO (sbasi) - Add support for manifest changes, aka projects
674 # have been added or deleted from the manifest.
675 if self.gitc_manifest: 673 if self.gitc_manifest:
676 gitc_manifest_projects = self.GetProjects(args, 674 gitc_manifest_projects = self.GetProjects(args,
677 manifest=self.gitc_manifest,
678 missing_ok=True) 675 missing_ok=True)
679 gitc_projects = [] 676 gitc_projects = []
680 opened_projects = [] 677 opened_projects = []
681 for project in gitc_manifest_projects: 678 for project in gitc_manifest_projects:
682 if not project.old_revision: 679 if project.relpath in self.gitc_manifest.paths and \
683 gitc_projects.append(project) 680 self.gitc_manifest.paths[project.relpath].old_revision:
681 opened_projects.append(project.relpath)
684 else: 682 else:
685 opened_projects.append(project) 683 gitc_projects.append(project.relpath)
686 684
687 if gitc_projects and not opt.local_only: 685 if not args:
686 gitc_projects = None
687
688 if gitc_projects != [] and not opt.local_only:
688 print('Updating GITC client: %s' % self.gitc_manifest.gitc_client_name) 689 print('Updating GITC client: %s' % self.gitc_manifest.gitc_client_name)
689 gitc_utils.generate_gitc_manifest(self.gitc_manifest.gitc_client_dir, 690 gitc_utils.generate_gitc_manifest(self.repodir,
691 self.gitc_manifest.gitc_client_name,
690 self.gitc_manifest, 692 self.gitc_manifest,
693 self.manifest.manifestFile,
691 gitc_projects) 694 gitc_projects)
692 print('GITC client successfully synced.') 695 print('GITC client successfully synced.')
693 696
694 # The opened projects need to be synced as normal, therefore we 697 # The opened projects need to be synced as normal, therefore we
695 # generate a new args list to represent the opened projects. 698 # generate a new args list to represent the opened projects.
696 args = [] 699 # TODO: make this more reliable -- if there's a project name/path overlap,
697 for proj in opened_projects: 700 # this may choose the wrong project.
698 args.append(os.path.relpath(proj.worktree, os.getcwd())) 701 args = [os.path.relpath(self.manifest.paths[p].worktree, os.getcwd())
702 for p in opened_projects]
699 if not args: 703 if not args:
700 return 704 return
701 all_projects = self.GetProjects(args, 705 all_projects = self.GetProjects(args,