summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,