diff options
| author | Mike Frysinger <vapier@google.com> | 2021-02-24 12:17:31 -0500 |
|---|---|---|
| committer | Mike Frysinger <vapier@google.com> | 2021-02-27 19:56:24 +0000 |
| commit | 6093d99d13deada12a2365e81e2bd148dbb423ad (patch) | |
| tree | 253e504fec53bdc4bfea2ca79d9f3bcd2df6df23 /subcmds/checkout.py | |
| parent | ebf04a4404e93c6d6b167775c90264dc24ed8c98 (diff) | |
| download | git-repo-6093d99d13deada12a2365e81e2bd148dbb423ad.tar.gz | |
checkout: add --jobs support
Use multiprocessing to run in parallel. When operating on multiple
projects, this can speed things up. Across 1000 repos, it goes from
~9sec to ~5sec with the default -j8.
Change-Id: Ida6dd565db78ff7bac0ecb25d2805e8a1bf78048
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/297982
Reviewed-by: Chris Mcdonald <cjmcdonald@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Diffstat (limited to 'subcmds/checkout.py')
| -rw-r--r-- | subcmds/checkout.py | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/subcmds/checkout.py b/subcmds/checkout.py index fbb13653..cf54ced7 100644 --- a/subcmds/checkout.py +++ b/subcmds/checkout.py | |||
| @@ -12,8 +12,11 @@ | |||
| 12 | # See the License for the specific language governing permissions and | 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. | 13 | # limitations under the License. |
| 14 | 14 | ||
| 15 | import functools | ||
| 16 | import multiprocessing | ||
| 15 | import sys | 17 | import sys |
| 16 | from command import Command | 18 | |
| 19 | from command import Command, DEFAULT_LOCAL_JOBS, WORKER_BATCH_SIZE | ||
| 17 | from progress import Progress | 20 | from progress import Progress |
| 18 | 21 | ||
| 19 | 22 | ||
| @@ -31,27 +34,41 @@ The command is equivalent to: | |||
| 31 | 34 | ||
| 32 | repo forall [<project>...] -c git checkout <branchname> | 35 | repo forall [<project>...] -c git checkout <branchname> |
| 33 | """ | 36 | """ |
| 37 | PARALLEL_JOBS = DEFAULT_LOCAL_JOBS | ||
| 34 | 38 | ||
| 35 | def ValidateOptions(self, opt, args): | 39 | def ValidateOptions(self, opt, args): |
| 36 | if not args: | 40 | if not args: |
| 37 | self.Usage() | 41 | self.Usage() |
| 38 | 42 | ||
| 43 | def _ExecuteOne(self, nb, project): | ||
| 44 | """Checkout one project.""" | ||
| 45 | return (project.CheckoutBranch(nb), project) | ||
| 46 | |||
| 39 | def Execute(self, opt, args): | 47 | def Execute(self, opt, args): |
| 40 | nb = args[0] | 48 | nb = args[0] |
| 41 | err = [] | 49 | err = [] |
| 42 | success = [] | 50 | success = [] |
| 43 | all_projects = self.GetProjects(args[1:]) | 51 | all_projects = self.GetProjects(args[1:]) |
| 44 | 52 | ||
| 45 | pm = Progress('Checkout %s' % nb, len(all_projects)) | 53 | def _ProcessResults(results): |
| 46 | for project in all_projects: | 54 | for status, project in results: |
| 47 | pm.update() | 55 | if status is not None: |
| 56 | if status: | ||
| 57 | success.append(project) | ||
| 58 | else: | ||
| 59 | err.append(project) | ||
| 60 | pm.update() | ||
| 48 | 61 | ||
| 49 | status = project.CheckoutBranch(nb) | 62 | pm = Progress('Checkout %s' % nb, len(all_projects)) |
| 50 | if status is not None: | 63 | # NB: Multiprocessing is heavy, so don't spin it up for one job. |
| 51 | if status: | 64 | if len(all_projects) == 1 or opt.jobs == 1: |
| 52 | success.append(project) | 65 | _ProcessResults(self._ExecuteOne(nb, x) for x in all_projects) |
| 53 | else: | 66 | else: |
| 54 | err.append(project) | 67 | with multiprocessing.Pool(opt.jobs) as pool: |
| 68 | results = pool.imap_unordered( | ||
| 69 | functools.partial(self._ExecuteOne, nb), all_projects, | ||
| 70 | chunksize=WORKER_BATCH_SIZE) | ||
| 71 | _ProcessResults(results) | ||
| 55 | pm.end() | 72 | pm.end() |
| 56 | 73 | ||
| 57 | if err: | 74 | if err: |
