summaryrefslogtreecommitdiffstats
path: root/subcmds/start.py
diff options
context:
space:
mode:
Diffstat (limited to 'subcmds/start.py')
-rw-r--r--subcmds/start.py250
1 files changed, 139 insertions, 111 deletions
diff --git a/subcmds/start.py b/subcmds/start.py
index 809df963..d7772b33 100644
--- a/subcmds/start.py
+++ b/subcmds/start.py
@@ -25,119 +25,147 @@ from project import SyncBuffer
25 25
26 26
27class Start(Command): 27class Start(Command):
28 COMMON = True 28 COMMON = True
29 helpSummary = "Start a new branch for development" 29 helpSummary = "Start a new branch for development"
30 helpUsage = """ 30 helpUsage = """
31%prog <newbranchname> [--all | <project>...] 31%prog <newbranchname> [--all | <project>...]
32""" 32"""
33 helpDescription = """ 33 helpDescription = """
34'%prog' begins a new branch of development, starting from the 34'%prog' begins a new branch of development, starting from the
35revision specified in the manifest. 35revision specified in the manifest.
36""" 36"""
37 PARALLEL_JOBS = DEFAULT_LOCAL_JOBS 37 PARALLEL_JOBS = DEFAULT_LOCAL_JOBS
38 38
39 def _Options(self, p): 39 def _Options(self, p):
40 p.add_option('--all', 40 p.add_option(
41 dest='all', action='store_true', 41 "--all",
42 help='begin branch in all projects') 42 dest="all",
43 p.add_option('-r', '--rev', '--revision', dest='revision', 43 action="store_true",
44 help='point branch at this revision instead of upstream') 44 help="begin branch in all projects",
45 p.add_option('--head', '--HEAD', 45 )
46 dest='revision', action='store_const', const='HEAD', 46 p.add_option(
47 help='abbreviation for --rev HEAD') 47 "-r",
48 48 "--rev",
49 def ValidateOptions(self, opt, args): 49 "--revision",
50 if not args: 50 dest="revision",
51 self.Usage() 51 help="point branch at this revision instead of upstream",
52 52 )
53 nb = args[0] 53 p.add_option(
54 if not git.check_ref_format('heads/%s' % nb): 54 "--head",
55 self.OptionParser.error("'%s' is not a valid name" % nb) 55 "--HEAD",
56 56 dest="revision",
57 def _ExecuteOne(self, revision, nb, project): 57 action="store_const",
58 """Start one project.""" 58 const="HEAD",
59 # If the current revision is immutable, such as a SHA1, a tag or 59 help="abbreviation for --rev HEAD",
60 # a change, then we can't push back to it. Substitute with 60 )
61 # dest_branch, if defined; or with manifest default revision instead. 61
62 branch_merge = '' 62 def ValidateOptions(self, opt, args):
63 if IsImmutable(project.revisionExpr): 63 if not args:
64 if project.dest_branch: 64 self.Usage()
65 branch_merge = project.dest_branch 65
66 else: 66 nb = args[0]
67 branch_merge = self.manifest.default.revisionExpr 67 if not git.check_ref_format("heads/%s" % nb):
68 68 self.OptionParser.error("'%s' is not a valid name" % nb)
69 try: 69
70 ret = project.StartBranch( 70 def _ExecuteOne(self, revision, nb, project):
71 nb, branch_merge=branch_merge, revision=revision) 71 """Start one project."""
72 except Exception as e: 72 # If the current revision is immutable, such as a SHA1, a tag or
73 print('error: unable to checkout %s: %s' % (project.name, e), file=sys.stderr) 73 # a change, then we can't push back to it. Substitute with
74 ret = False 74 # dest_branch, if defined; or with manifest default revision instead.
75 return (ret, project) 75 branch_merge = ""
76 76 if IsImmutable(project.revisionExpr):
77 def Execute(self, opt, args): 77 if project.dest_branch:
78 nb = args[0] 78 branch_merge = project.dest_branch
79 err = [] 79 else:
80 projects = [] 80 branch_merge = self.manifest.default.revisionExpr
81 if not opt.all: 81
82 projects = args[1:] 82 try:
83 if len(projects) < 1: 83 ret = project.StartBranch(
84 projects = ['.'] # start it in the local project by default 84 nb, branch_merge=branch_merge, revision=revision
85 85 )
86 all_projects = self.GetProjects(projects, 86 except Exception as e:
87 missing_ok=bool(self.gitc_manifest), 87 print(
88 all_manifests=not opt.this_manifest_only) 88 "error: unable to checkout %s: %s" % (project.name, e),
89 89 file=sys.stderr,
90 # This must happen after we find all_projects, since GetProjects may need 90 )
91 # the local directory, which will disappear once we save the GITC manifest. 91 ret = False
92 if self.gitc_manifest: 92 return (ret, project)
93 gitc_projects = self.GetProjects(projects, manifest=self.gitc_manifest, 93
94 missing_ok=True) 94 def Execute(self, opt, args):
95 for project in gitc_projects: 95 nb = args[0]
96 if project.old_revision: 96 err = []
97 project.already_synced = True 97 projects = []
98 else: 98 if not opt.all:
99 project.already_synced = False 99 projects = args[1:]
100 project.old_revision = project.revisionExpr 100 if len(projects) < 1:
101 project.revisionExpr = None 101 projects = ["."] # start it in the local project by default
102 # Save the GITC manifest. 102
103 gitc_utils.save_manifest(self.gitc_manifest) 103 all_projects = self.GetProjects(
104 104 projects,
105 # Make sure we have a valid CWD 105 missing_ok=bool(self.gitc_manifest),
106 if not os.path.exists(os.getcwd()): 106 all_manifests=not opt.this_manifest_only,
107 os.chdir(self.manifest.topdir) 107 )
108 108
109 pm = Progress('Syncing %s' % nb, len(all_projects), quiet=opt.quiet) 109 # This must happen after we find all_projects, since GetProjects may
110 for project in all_projects: 110 # need the local directory, which will disappear once we save the GITC
111 gitc_project = self.gitc_manifest.paths[project.relpath] 111 # manifest.
112 # Sync projects that have not been opened. 112 if self.gitc_manifest:
113 if not gitc_project.already_synced: 113 gitc_projects = self.GetProjects(
114 proj_localdir = os.path.join(self.gitc_manifest.gitc_client_dir, 114 projects, manifest=self.gitc_manifest, missing_ok=True
115 project.relpath) 115 )
116 project.worktree = proj_localdir 116 for project in gitc_projects:
117 if not os.path.exists(proj_localdir): 117 if project.old_revision:
118 os.makedirs(proj_localdir) 118 project.already_synced = True
119 project.Sync_NetworkHalf() 119 else:
120 sync_buf = SyncBuffer(self.manifest.manifestProject.config) 120 project.already_synced = False
121 project.Sync_LocalHalf(sync_buf) 121 project.old_revision = project.revisionExpr
122 project.revisionId = gitc_project.old_revision 122 project.revisionExpr = None
123 pm.update() 123 # Save the GITC manifest.
124 pm.end() 124 gitc_utils.save_manifest(self.gitc_manifest)
125 125
126 def _ProcessResults(_pool, pm, results): 126 # Make sure we have a valid CWD.
127 for (result, project) in results: 127 if not os.path.exists(os.getcwd()):
128 if not result: 128 os.chdir(self.manifest.topdir)
129 err.append(project) 129
130 pm.update() 130 pm = Progress("Syncing %s" % nb, len(all_projects), quiet=opt.quiet)
131 131 for project in all_projects:
132 self.ExecuteInParallel( 132 gitc_project = self.gitc_manifest.paths[project.relpath]
133 opt.jobs, 133 # Sync projects that have not been opened.
134 functools.partial(self._ExecuteOne, opt.revision, nb), 134 if not gitc_project.already_synced:
135 all_projects, 135 proj_localdir = os.path.join(
136 callback=_ProcessResults, 136 self.gitc_manifest.gitc_client_dir, project.relpath
137 output=Progress('Starting %s' % (nb,), len(all_projects), quiet=opt.quiet)) 137 )
138 138 project.worktree = proj_localdir
139 if err: 139 if not os.path.exists(proj_localdir):
140 for p in err: 140 os.makedirs(proj_localdir)
141 print("error: %s/: cannot start %s" % (p.RelPath(local=opt.this_manifest_only), nb), 141 project.Sync_NetworkHalf()
142 file=sys.stderr) 142 sync_buf = SyncBuffer(self.manifest.manifestProject.config)
143 sys.exit(1) 143 project.Sync_LocalHalf(sync_buf)
144 project.revisionId = gitc_project.old_revision
145 pm.update()
146 pm.end()
147
148 def _ProcessResults(_pool, pm, results):
149 for result, project in results:
150 if not result:
151 err.append(project)
152 pm.update()
153
154 self.ExecuteInParallel(
155 opt.jobs,
156 functools.partial(self._ExecuteOne, opt.revision, nb),
157 all_projects,
158 callback=_ProcessResults,
159 output=Progress(
160 "Starting %s" % (nb,), len(all_projects), quiet=opt.quiet
161 ),
162 )
163
164 if err:
165 for p in err:
166 print(
167 "error: %s/: cannot start %s"
168 % (p.RelPath(local=opt.this_manifest_only), nb),
169 file=sys.stderr,
170 )
171 sys.exit(1)