Compare commits

...

74 Commits

Author SHA1 Message Date
03ff276cd7 sync: properly handle standalone manifests for sync command
sync should not attempt to sync the manifest project if it was
created from a standalone manifest. The current work around is to
run sync with --nmu.

BUG=none
TEST=manual runs

Change-Id: I2e121af0badf9642143e77c7af89d1c2d993b0f3
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/321195
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-10-15 17:20:00 +00:00
4ee4a45d03 subcmds/sync: Use pack-refs instead of gc for redundant gitdirs.
Previously `git gc` was being run on every gitdir even when they shared
the same objects. Instead only call it once and use pack-refs for the
gitdirs that were not gc'ed.

Bug: https://crbug.com/gerrit/15113
Test: repo sync -j # and check that git pack-refs is called
Change-Id: Icff37ab3ec78cfb44391d8cc7f2d875991532320
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/320275
Tested-by: Allen Webb <allenwebb@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-10-14 12:27:12 +00:00
0f6f16ed17 repo: more arg checking for --standalone-manifest re-inits
`repo init` doesn't do anything on re-init when the checkout has
been initialized using --standalone manifest. Rather than let the
tool run through its existing flows (which happen to noop), check
the args and explicitly quit if a bare `repo init` is run on a
standalone checkout.

BUG=none
TEST=manual tests

Change-Id: Ie4346ef6df1282ec3e3f8045a08138c93653fece
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/320735
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-10-11 18:58:11 +00:00
76491590b8 repo: fix bug with --standalone-manifest
We were accidentally always setting manifest.standlone in config,
which was messing up behavior for standard use cases.

BUG=gerrit:15160
TEST=manual runs

Change-Id: Ic80f084ae97de5721aced3bb52d3ea9115f8d833
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/320715
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-10-11 18:57:57 +00:00
6a74c91f50 sign-launcher: make the help text more automatic
Rather than display "3.0" all the time and confuse people, extract
the version from the launcher we're signing and display that.

Also reformat the text to follow our current practice: upload the
versioned launcher by itself first, and then later copy that over
the default.

And while we're here, add tips for rollbacks.

Change-Id: I1654425c88e5c67d78879f2f33ad685c59be14dc
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319637
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-10-06 17:02:56 +00:00
669efd0fd7 subcmds/sync: Disable autoDetach for git gc.
gc.autoDetach is enabled by default which makes 'git gc --auto' return
immediately and run in background. This can lead to a pile up of
operations all using large amounts of memory at the same time. To avoid
this set gc.autoDetach to false so that the garbage collect task waits
for instances to finish before spawning more.

Bug: https://crbug.com/gerrit/15113
Test: repo sync -j # and check the number of 'git gc' processes
Change-Id: Ic0815156ba3db03972968f33f6f9f51e4928f23b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319835
Tested-by: Allen Webb <allenwebb@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-10-05 14:12:01 +00:00
a0f6006ae7 git_config: Fixed test.gitconfig getting updated when running tests.
Moved test_GetSyncAnalysisStateData to GitConfigReadWriteTests class.

Deleted [repo "syncstate*..] data from tests/fixtures/test.gitconfig.

Tested:
./run_tests
...
tests/test_git_config.py::GitConfigReadWriteTests::test_GetSyncAnalysisStateData PASSED [ 84%]
...

Bug: https://crbug.com/gerrit/15103
Change-Id: I8cb89ce10b025994a045106c9c66dd243ae8ba50
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319557
Tested-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-30 21:45:09 +00:00
2ddbf8a8bf Merge "Merge history of v2.14.5." into main 2021-09-30 21:37:09 +00:00
445723fd37 Merge history of v2.14.5.
The v2.14.[345] releases were cut on a branch based on v2.14.2.  We
had some regression fixes we wanted in v2.14, but too many risky
changes landed in main since to cut another v2.14.x directly, and
we didn't want to destabilize even more by pushing a v2.15 right
away.  So we branched to keep things healthy.

But people with old checkouts trying to upgrade from those versions
run into an old repo bug where it only selfupdates with fast-forwards,
and repo can't fast-forward from those divergent histories.  So let's
do a merge commit to stitch the history back together.

There's no actual changes in here.

Change-Id: I05a96048e3846321e57c5f5224fb8dcf3c191d35
2021-09-30 21:36:56 +00:00
436bde5137 Merge history of v1.13.11.
For older versions of repo, this would make it easier for it to perform
a self update by making it a fast-forward from the following tags:

  v1.13.9.2, v1.13.9.3, v1.13.9.4, v1.13.10, v1.13.11

Change-Id: Ia75776312eaf802a150db8bd7c0a6dce57914580
2021-09-30 11:49:08 -07:00
4f88206178 trace2_event: Add remove_prefix to fix failing tests on Linux & macOS.
removeprefix is available i python 3.9. Mac and Linux are running in
a version below 3.9. Thus tests are failing with the following error:
  "AttributeError: 'str' object has no attribute 'removeprefix' "

Replaced the removeprefix with custom function which we will delete
once Linux and macOS versions are updated.

Tested:
$ ./run_tests

Bug: [google internal] b/201453085
Change-Id: I9b4d564ff1176e1b4471805ef05472c1914cd9f9
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319375
Tested-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-29 21:24:59 +00:00
f88282ccc2 git_config: update error handling with no config file
Now that _do throws an exception when `git` fails, update the logic
that tries to read config files but the file doesn't exist.

Bug: b/192664812
Change-Id: I6417ecd70891b8f2d5f2bdb819f91df69ac4b70c
Test: `repo upload` no longer crashes when .repo/config doesn't exist
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319295
Reviewed-by: Jack Neus <jackneus@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-09-29 01:02:47 +00:00
8967a5aec6 launcher: bump version for new release
Change-Id: I9812185c9dfc11289547f5956c0cbe567d720f7f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319335
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-09-28 20:54:56 +00:00
2f3c3316e4 Update revisionId if required when using extend-project
When a hard revision ID is provided in a regular project tag then the
revisionId is updated as well if it is a commit hash.  The difference
is that if the revisionExpr is a commit, git-repo needs to update
refs/remotes/m/master with update-ref not symbolic-ref, as the latter
must refer to another ref, not to a specific commit.

Change-Id: I215a62dabb30225e480ad2c731416d775fc0c750
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/310963
Tested-by: Michael Kelly <mkelly@arista.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-28 20:12:00 +00:00
37c21c268b Add 'dest-path' to extend-project to support changing path
This allows us to move the repository to a new location in the source
tree without having to remove-project + add a new project tag.

Change-Id: I4dba6151842e57f6f2b8fe60cda260ecea68b7b4
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/310962
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Michael Kelly <mkelly@arista.com>
2021-09-28 20:12:00 +00:00
b12c369e0b superproject: Only trigger enrollment logic when manifest have it.
The current code would check for enrollment status when the user did not
explicitly specify --[no-]use-superproject and do not have a remembered
value in their repo client. However, because superproject only makes
sense for manifests that have one specified, we should skip the
enrollment logic in that case.

Address this by checking manifest.superproject prior to proceeding. This
would avoid showing the greeting message of superproject enrollment
which can be confusing for developers.

Tested:
  For manifest without superproject:
   - repo sync --use-superproject will still show message for
     superproject;
   - repo sync will not show message regardless of enrollment state
  For manifest with superproject:
   - repo sync will show message and perform enrollment if not
     previously enrolled

Bug: https://crbug.com/gerrit/15039
Change-Id: Ic2be9f9d037f0e7cf3446da474a5a0d0e4bd88da
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319255
Tested-by: Xin Li <delphij@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-28 19:42:01 +00:00
bbe8836494 superproject: Log syncstate's parameter as data-json it it is an array.
All the values of syncstate are strings, check the first byte and last
byte to see if it is an array. For syncstate data, there were no false
positives.

Tested:
$ repo_dev sync

Verified event logged for argv is "data-json".

$./run_tests

Bug: [google internal] b/201102002
Change-Id: Id56adb532b80267f08d09147ac663cdd5987ce87
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319075
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-09-28 18:22:49 +00:00
9d96f58f5f make file removal a bit more robust
Some of the file removal calls are subject to race conditions (if
something else deletes the file), so extend our remove API to have
an option to ignore ENOENT errors.  Then update a bunch of random
call sites to use this new functionality.

Change-Id: I31a9090e135452033135337a202a4fc2dbf8b63c
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319195
Reviewed-by: Sean McAllister <smcallis@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-09-28 16:06:50 +00:00
7a1e7e772f repo: add support for reading standalone manifests from disk
BUG=b:192664812
TEST=existing tests (no coverage), manual runs

Change-Id: Ic032417ecfca77d5e0de1b1ff62b30ce8205bfc5
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/318715
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-28 16:03:21 +00:00
c474c9cba1 repo: Add support for standalone manifests
Added --standalone_manifest to repo tool. If set, the
manifest is downloaded directly from the appropriate source
(currently, we only support GS) and used instead of creating
a manifest git checkout. The manifests.git repo is still created to
keep track of various config but is marked as being for a standalone
manifest so that the repo tool doesn't try to run networked git
commands in it.

BUG=b:192664812
TEST=existing tests (no coverage), manual runs

Change-Id: I84378cbc7f8e515eabeccdde9665efc8cd2a9d21
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312942
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-28 15:40:46 +00:00
956f7363d1 superproject: Log argv parameter of syncstate as 'data-json'.
Fixed: "we need to make a special case for logging the argv; it
should probably be a "data-json" event so that we log this directly as
an array rather than an encoded string.

Tested:
$ repo_dev sync

Verified event logged for argv is "data-json".

$./run_tests

Bug: [google internal] b/201102002
Change-Id: I18ccec79c73c8dc931cb8afc472b2361db8aea4c
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/319055
Reviewed-by: Josh Steadmon <steadmon@google.com>
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-09-27 19:11:14 +00:00
6f8c1bf4ff Fix indent error which would have prevented choice expiration to work.
Change-Id: I077e05eea23ad58d1dde2c9fe5608660a56d03e5
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/318815
Tested-by: Xin Li <delphij@google.com>
Reviewed-by: Amith Dsouza <amithds@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
2021-09-27 18:59:21 +00:00
e0b16a22a0 superproject: support a new revision attribute.
Tested:
$ ./run_tests

Verified that a manifest that specified superproject revision would use
the specified revision, and superproject will use the default revision.

Note that this is a slight behavior change from earlier repo versions,
which would always use the branch name of the manifest itself. However,
the new behavior would be more consisitent with regular "project"
element and would allow superproject be used even if it is not enabled
for the particular manifest branch, so we have decided to make the
change as it would provide more flexibility and better matches what
other elements would do.

Bug: [google internal] b/187868160
Change-Id: I35255ee347aff6e65179f7879d52931f168b477e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/317643
Tested-by: Xin Li <delphij@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-27 06:36:05 +00:00
d669d2dee5 release-process: update distro baseline & add OpenSSH
Stop tracking Ubuntu Trusty & Xenial and Debian Jessie & Stretch
as they only had Python 3.5 available which we've dropped.

Backfill OpenSSH versions since we've started testing for it.

Change-Id: I03183ed97f6e43dce8a00e36cce2956544a26afc
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/318835
Reviewed-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-09-24 16:42:56 +00:00
366824937c platform_utils: os.rename exception when src and des on different file system
Symptom: repo sync exception
Root Cause: os.rename only works when source and destination are on the same file system
Solution: using shutil.move

to save disk usage, I create links for projects and project-objects, link to folder on another disk
lrwxrwxrwx  1 owenwen owenwen   47 Jun  9 16:40 project-objects -> /disk3/AndroidLocalRepos/.repo/project-objects/
lrwxrwxrwx  1 owenwen owenwen   40 Jun  9 16:40 projects -> /disk3/AndroidLocalRepos/.repo/projects/

below are exception I met:
"""
Traceback (most recent call last):
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 44, in mapstar
    return list(map(*args))
  File "/disk2/Android11/.repo/repo/subcmds/sync.py", line 550, in _CheckoutOne
    project.Sync_LocalHalf(syncbuf, force_sync=force_sync)
  File "/disk2/Android11/.repo/repo/project.py", line 1251, in Sync_LocalHalf
    self._InitWorkTree(force_sync=force_sync, submodules=submodules)
  File "/disk2/Android11/.repo/repo/project.py", line 2801, in _InitWorkTree
    self._CheckDirReference(self.gitdir, dotgit, share_refs=True)
  File "/disk2/Android11/.repo/repo/project.py", line 2674, in _CheckDirReference
    platform_utils.rename(dst_path, src_path)
  File "/disk2/Android11/.repo/repo/platform_utils.py", line 127, in rename
    os.rename(src, dst)
OSError: [Errno 18] Invalid cross-device link: '/disk2/Android11/system/libhidl/.git/packed-refs' -> '/disk2/Android11/.repo/projects/system/libhidl.git/packed-refs'
"""

Change-Id: Ifda2f16530cc5a8f280169f482ee858f9e5241d3
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/316002
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-09-24 08:20:06 +00:00
a84f43a006 manifest: make repo-hooks more robust wrt element ordering
Currently, repo will fail to sync to a manifest if the definition
of the repo-hooks project comes after the repo-hooks element.

BUG=none
TEST=new test, run_tests

Change-Id: I0bf85625173492af6c6404d4b67543e96e670562
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/318520
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Jack Neus <jackneus@google.com>
2021-09-23 21:17:38 +00:00
0468feac39 update-manpages: avoid regen just for datestamp update
To avoid noise due to the passage of time, don't regenerate man pages
if the only thing different is the datestamp in the header.

Change-Id: Ic8d7b08d12e59c66994c0cc2d4ec2d2ed3eb6e6d
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/318575
Reviewed-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-09-22 19:37:35 +00:00
0ec2029833 superproject: Move enrollment to opt-out when enabled globally
Our internal experiments was a success so far and we are enrolling 100%
users now.  Instead of asking every two weeks, simply consider a lack of
unexpired choice as accepting the system default.

With this change the user would still be able to override the system
default with --no-use-superproject, or to permanently set the choice in
user's profile with git config --global repo.superprojectchoice.

Bug: [google internal] b/190688390
Change-Id: Idc77a9cbf88a169d90304169e91f0d722dc4ac8b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/317975
Tested-by: Xin Li <delphij@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
2021-09-20 07:21:22 +00:00
d8e8ae8990 superproject: Log branch and remote url with every log message.
Saved superproject's remote URL in _remote_url data and used it
in the _Fecth function.

Tested:
$ ./run_tests
$ flake8 git_superproject.py
$ repo_dev init --use-superproject -u https://android.googlesource.com/platform/manifest
$ repo_dev sync

   Verified the all log messages have the following format.
   repo superproject branch: <branch> url: <url> warning: <message>

Bug: [google internal] b/200072098
Change-Id: Iac6af7c99225479fd50bc6909396b22e0ce5f76b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/318177
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-09-16 15:46:19 +00:00
6448a4f2af sync: Log repo sync state events as 'data' events.
git_trace2_event_log.py:
+ Added LogDataConfigEvents method to log 'data' events.
  Sync's current_sync_state and previous_sync_state are logged
  as 'data' events in the current log.

  It logs are key/value in the |config| argument. Each key is
  prefixed with |prefix| argument.

  The following are sample events that are logged during repo sync.

   {"event":"data",
   "sid":"repo-20210914T181545Z-P000330c0/repo-20210914T181545Z-P000330c0",
   "thread":"MainThread",
   "time":"2021-09-14T18:16:19.935846Z",
   "key":"previous_sync_state/repo.syncstate.main.synctime",
   "value":"2021-09-14T17:27:11.573717Z"}

   {"event":"data",
   "sid":"repo-20210914T181545Z-P000330c0/repo-20210914T181545Z-P000330c0",
   "thread":"MainThread",
   "time":"2021-09-14T18:16:19.955546Z",
   "key":"current_sync_state/repo.syncstate.main.synctime",
   "value":"2021-09-14T18:16:19.935979Z"}

tests/test_git_trace2_event_log.py:
+ Added unit tests

sync.py:
+ Changed logging calls to LogDataConfigEvents.

Tested:
$ ./run_tests

Tested it by running the following command multiple times.
$ repo_dev sync -j 20
  repo sync has finished successfully

  Verified config data is looged in trace2 event logs.

Bug: [google internal] b/199758376
Change-Id: I75fd830e90c1811ec28510538c99a2632b104e85
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/317823
Reviewed-by: Josh Steadmon <steadmon@google.com>
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-09-14 21:36:12 +00:00
1328c35a4d superproject: Provide accurate feedback for user choice
Currently the code would give a message that would appear like the user
have enrolled the experiment regardless of the actual choice. For users
who choose to not enroll in the experiment, we should give them
instructions to override (enable) superproject once instead of how to
disable it, which is what the code already behave.

Bug: [google internal] b/199167992
Change-Id: Iba3314cb510aedf024375a26baa8bc1d5e2846cf
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/317382
Tested-by: Xin Li <delphij@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
2021-09-08 20:35:42 +00:00
7f8bd85184 superoject: log error message in the 'fmt' field also.
Tested:
+ Verified error messages are being collected.

Bug: [google internal] b/193711236
Change-Id: I6c608a2af332ccd38722b7f83a82e5ac8fa143db
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/317162
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-09-03 00:32:04 +00:00
c63328e5ff docs: Add version for Ubuntu 21.04 Hirsute and Debian 11 Bullseye
* Add footer to the version table, so easier to read and maintain.
* Add version entry for Ubuntu 21.04 Hirsute (non-LTS).
* Add version entry for Debian 11 Bullseye (LTS).

Change-Id: Ic72f911e616b1a13901e56074004f05cdc2c7633
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/313322
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Xin Li <delphij@google.com>
2021-09-03 00:16:43 +00:00
b55769a5c9 superproject: print messages if the manifest has superproject tag.
1) If the manifest has superproject tag (git_master, etc), then
   display error/warning messages (as it is doing today)
2) If the manifest doesn't have superproject tag (nest, chromeos
   manifests), then don't display any error/warning messages about
   superrproject (behave as though user has specified
   --no-use-superproject).
3) Print error/warning messages if --use-superproject passed as
   argument to repo sync.
4) No change in behavior for the repo init command.

git_superproject.py:
+ Fixed typo in _WriteManifestFile method name
+ Superproject accepts print_message  as an argument and it defaults
  to True. All messages that are printed to stderr are controlled by
  this flag. If it is True, then messages get printed.
+ Added PrintMessages function which return true if either
  --use-superproject is specified on the command line or if the
  manifest has a superproject tag.

sync.py:
+ Displays the warning message if PrintMessgages are enabled and
  passes that as argument to superproject object.
+ Added 'hassuperprojecttag' trace2 log entry for analysis. We can
  find users/branches that are using superproject, but the manifest is
  missing the superproject tag.

Tested:
$ ./run_tests

+ Verified printing of messages with and without superproject tag, with
  with --use-superproject option.

+ aosp-master
  $ repo_dev init --use-superproject -u https://android.googlesource.com/platform/manifest
  $ repo_dev sync

+ A manifest without superproject tag.
  $ repo_dev init -m $(pwd)/manifest_7482982.xml
  $ repo_dev sync -n -c -j32 -m $(pwd)/manifest_7482982.xml

Bug: [google internal] b/196411099
Change-Id: I92166dcad15a4129fab82edcf869e7c8db3efd4b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/314982
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-08-13 20:07:40 +00:00
5637afcc60 superproject: prepend messages with - "repo superproject"
Changed _LogError method to _LogWarning.

Replaced 'repo error:' with "repo superproject warning:"(except IOError
message, which is still an "repo superproject error:" message)

Tested:
$ ./run_tests

Tested the errors and warnings by forcing the error/warning.
$ repo_dev sync -j 20 --use-superproject platform/packages/apps/Music
  ...
  repo superproject warning: please file a bug using go/repo-bug to report missing commit_ids for: []
  ...
  repo superproject error: cannot write manifest to : /sdc/android/src/aosp/.repo/exp-superproject/superproject_override.xml
  ...

Bug: [google internal] b/193711236

Change-Id: Ia0b6c830e04cf18dfc1a2ce325181a5b1160e054
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/314642
Tested-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Ian Kasprzak <iankaz@google.com>
Reviewed-by: Xin Li <delphij@google.com>
2021-08-12 16:30:26 +00:00
df8b1cba47 man: make output system independent
The current help output might change based on the number of CPU cores
available (since it reflects the dynamic --jobs logic).  This is good
for users running repo locally, but not good for shipping static man
pages.  Hook the help output to have it generate the same output all
the time.

Change-Id: I3098ceddc0ad914b0b8e3b25d660b5a264cb41ee
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312882
Reviewed-by: Roger Shimizu <rosh@debian.org>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-31 11:39:35 +00:00
9122bfc3a8 sync: Remove '_' from the repo.syncstate.* keys when saved to config.
GitConfig doesn't save keys if the keys contain "_" characters. Some
of the options like mp_update, use_superproject have underscores.

This fixes issue with previous_sync_state missing some of the options.

Tested:
$ ./run_tests

$ repo_dev init --use-superproject -u https://android.googlesource.com/platform/manifest

Tested it by running the sync command multiple times and verifing
previous_sync_state and current_sync_state have the same keys.

$ repo_dev sync -j 20
  repo sync has finished successfully

  Verified config file has [syncstate ...] data saved.

Bug: [google internal] b/188573450
Change-Id: I16b52a164f9dd1633d7dad1d8cf6b151c629fcb1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/313242
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-07-29 22:41:57 +00:00
7954de13b7 sync: Added logging of repo sync state and config options for analysis.
git_config.py:
+ Added SyncAnalysisState class, which saves the following data
  into the config object.
  ++ sys.argv, options, superproject's logging data.
  ++ repo.*, branch.* and remote.* parameters from config object.
  ++ current time as synctime.
  ++ Version number of the object.
+ All the keys for the above data are prepended with 'repo.syncstate.'
+ Added GetSyncAnalysisStateData and UpdateSyncAnalysisState methods
  to GitConfig object to save/get the above data.

git_trace2_event_log.py:
+ Added LogConfigEvents method with code from DefParamRepoEvents
  to log events.

sync.py:
+ superproject_logging_data is a dictionary that collects all the
  superproject data that is to be logged as trace2 event.
+ Sync at the end logs the previously saved syncstate.* parameters
  as previous_sync_state. Then it calls config's UpdateSyncAnalysisState
  to save and log all the current options, superproject logged data.

docs/internal-fs-layout.md:
+ Added doc string explaining [repo.syncstate ...] sections of
  .repo/manifests.git/config file.

test_git_config.py:
+ Added unit test for the new methods of GitConfig object.

Tested:
$ ./run_tests

$ repo_dev init --use-superproject -u https://android.googlesource.com/platform/manifest

Tested it by running the following command multiple times.
$ repo_dev sync -j 20
  repo sync has finished successfully

  Verified config file has [syncstate ...] data saved.

Bug: [google internal] b/188573450
Change-Id: I1f914ce50f3382111b72940ca56de7c41b53d460
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/313123
Tested-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Xin Li <delphij@google.com>
2021-07-29 19:20:57 +00:00
ae86a46022 superproject: Skip updating of superproject when -l is used with sync.
Skip updating the superproject when -l is present and use the existing
superproject, if available (this would make sync -l work as it's
intended to do), and fall back to sync without superproject when not
(this would catch the case when superproject is enabled by automatic
rollout).

Tested:
$ repo sync -j 20 -n
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
/usr/local/google/home/rtenneti/work/android/src/aosp/.repo/exp-superproject/925043f706ba64db713e9bf3b55987e2-superproject.git: Initial setup for superproject completed.
Fetching: 100% (1032/1032), done in 41.184s
...

$ repo_dev sync -j 20 -l
prebuilts/asuite/: discarding 1 commits
prebuilts/runtime/: discarding 1 commits
...
repo sync has finished successfully.

+ With superproject-override.xml and test it.

  $ ls -l .repo/exp-superproject/
  total 176
  drwxr-xr-x 7 rtenneti primarygroup   4096 Jul 27 14:10 925043f706ba64db713e9bf3b55987e2-superproject.git
  -rw-r--r-- 1 rtenneti primarygroup 172742 Jul 27 14:10 superproject_override.xml
  rtenneti@rtenneti:~/work/android/src/aosp$ repo_dev sync -j 20 -l
  ...
  repo sync has finished successfully.

+ Rename the file superproject-override.xml and test it.
  $ ls -l .repo/exp-superproject/
  total 176
  drwxr-xr-x 7 rtenneti primarygroup   4096 Jul 27 14:10 925043f706ba64db713e9bf3b55987e2-superproject.git
  -rw-r--r-- 1 rtenneti primarygroup 172742 Jul 27 14:10 temp.xml

  $ repo_dev sync -j 20 -l
  Checking out:  1% (12/1031) platform/external/rust/crates/fallible-streaming-iteexternal/linux-kselftest/: discarding 1 commits
  prebuilts/remoteexecution-client/: discarding 1 commits
  Checking out: 51% (536/1031) platform/prebuilts/gcc/darwin-x86/aarch64/....
  ....
  Checking out: 100% (1031/1031), done in 5.478s
  repo sync has finished successfully.

Bug: [google internal] b/184368268
Change-Id: I3aba5872e4f7c299977b92c2a39847ef28698c5a
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312962
Reviewed-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Jonathan Nieder <jrn@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-07-28 16:12:53 +00:00
73c43b839f repo: add --show-toplevel akin to git
Simple API to make it easy to find the top of the repo client checkout
for users.  This mirrors the `git rev-parse --show-toplevel` API.

Change-Id: I0c3f98def089d0fc9ebcfa50aa3dc02091c1c273
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312909
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-28 05:38:53 +00:00
56345c345b repo: refactor help output handling
Currently we have the behavior:
* `repo`: Equivalent to `repo help` -- only shows common subcommands
  (with short description), and then exits 0.
* `repo --help`: Shows repo's core options, lists all commands (no
  specific info), and then exits 0.

The first case is not behaving well:
* If you run `repo` without a specific subcommand, that's an error,
  so we should be exiting 1 instead.
* Showing only subcommands and no actual option summary makes it seem
  like repo itself doesn't take any options.  This confuses users.

Let's rework things a bit.  Now we have the behavior:
* `repo`: Shows repo's core options, lists all commands (no specific
  info), and then exits 1.
* `repo --help`: Shows repo's core options, shows common subcommands
  (with short description), and then exits 0.
* `repo --help-all`: Shows repo's core options, shows all subcommands
  (with short description), and then exits 0.

Basically we swap the behavior of `repo` and `repo --help`, and fix
the exit status when the subcommand is missing.

The addition of --help-all is mostly for the man pages.  We were
relying on `repo help --all` to generate the repo(1) man page, but
that too omitted the core repo options.  Now the man page includes
all the core repo options and provides a summary of all commands.

Change-Id: I1f99b99d5b8af2591f96a078d0647a3d76d6b0fc
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312908
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-28 05:38:34 +00:00
a024bd33b8 repo: make --version always work
We don't really care what the subcommand is set to when --version
output is requested, so stop enforcing it.  This fixes some weird
behavior like `repo --version version` fails, but `repo --version
help` works.

The new logic skips subcommand validation, so `repo --version asdf`
will still display the version output.  This matches git behavior,
and makes a bit of sense when we consider that the user really wants
to see the tool version, and probably doesn't care about anything
else on the command line.

Change-Id: I87454d473c2c8869344b3888a7affaa2e03f5b0f
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312907
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-28 05:37:52 +00:00
968d646f04 repo: refactor internal --help/--version parsing
The _ParseArgs method parses the arguments and processes some of
the options, with the rest left to the _Run method.  Simplify the
_ParseArgs method to only parse arguments and have _Run handle all
actual processing.

This will make it easier to add more terminal options (ones that
exit immediately without a subcommand), and makes it easier to
understand the overall code flow.

Change-Id: I47f7274c3f2b59378fd479e403e70fb24b681536
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312906
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-28 05:37:27 +00:00
cfa00d6e3d bash-completion: complete projects with repo forall
We need to add a little bit more logic here so we stop completing
projects once we see the -c argument.

Bug: https://crbug.com/gerrit/14797
Change-Id: Ic2ba4f3dd616ec49d8ad754ff62d0d6e0250dbe6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312905
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-27 06:20:52 +00:00
5467185db0 list: add a --relative-to option
The current list output only shows project paths relative to the
root of the repo client checkout.  It can be helpful to also get
a listing of paths based on other paths (e.g. the current working
directory), so add an option to repo list to support that.  We'll
leverage this in bash completion to support completing projects by
their local paths and not just remote names.

Bug: https://crbug.com/gerrit/14797
Change-Id: Ia2b35d18c890217768448118b003874a1016efd4
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312904
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-27 06:20:52 +00:00
b380322174 bash-completion: refactor unique subcommand processing
Let's keep the main processing loop free of subcommand implementations
by pulling the existing help & start commands into dedicated functions.
Having a single giant function is harder to track as we add more and
more logic in.

Bug: https://crbug.com/gerrit/14797
Change-Id: I2b62dc430c0e7574f09aa4838f4ef03fbe4bf7fb
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312903
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-27 06:20:52 +00:00
13d6c94cfb bash-completion: fallback to default completion
If we can't provide any completions, then fallback to the standard
bash & readline ones.  This allows completion based on the user's
settings (e.g. local paths) to kick in.

Bug: https://crbug.com/gerrit/14797
Test: `repo rebase ./src/<tab>` works in a CrOS checkout
Change-Id: Iced343c4fc6fd3a932aab99875c1346687d187b6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312902
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-27 06:20:52 +00:00
6ea0caea86 repo: properly handle remote annotations in manifest_xml
BUG=b:192664812
TEST=tests/

Change-Id: I1aa50260f4a00d3cebbd531141e1626825e70127
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312643
Tested-by: Jack Neus <jackneus@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-07-23 18:03:11 +00:00
8e983bbc0f Force a fetch when superproject has a newer SHA1 for remote branch.
For older git-repo versions, we might have only fetched the SHA1
revision that was provided by the project, but have remote branch left
intact as long as they exist. When the remote branch become stale,
some repo operations like rebase would fail, and repo sync would not
correct this situation.

Fix this by tightening the requirement to also require the superproject
provided SHA1 be an ancestor or equal to the tip-of-tree of the remote
branch.

Bug: [google internal] b/193798453
Change-Id: Ie34c5d860dabb1cbd9f822da929088ec69c79cf6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312642
Tested-by: Xin Li <delphij@google.com>
Reviewed-by: Raman Tenneti <rtenneti@google.com>
2021-07-20 23:26:01 +00:00
c34b91c9d8 manifest: Support ignoring local manifests with 'repo manifest'
Currently users need to look up the baseline manifest by loading the
specific manifest file.  This exposes them to the internals of how the
manifest is stored which may potentially be fragile (eg: It was
switched from a symlink pointing at the file in the report to an
actual file with an 'include' tag).

Instead of doing this, we can provide an option to the 'repo manifest'
command which will emit the baseline manifest and decouple users from
the internal manifest details.

Change-Id: I12ee9160feaa591484ae71f404bc529be500ae4e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/311202
Tested-by: Michael Kelly <mkelly@arista.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-07-20 04:56:12 +00:00
0a1f533e28 Add script 'release/update-manpages' to generate manpages
Debian package started to ship manpages for repo since 2.8 [1]
And it's about for one year. So I think it should be upstreamed.

The script depends on help2man, which is available in both debian [2]
and ubuntu [3].

[1] https://tracker.debian.org/news/1150858/accepted-repo-28-1-source-into-unstable
[2] https://tracker.debian.org/pkg/help2man
[3] https://launchpad.net/ubuntu/+source/help2man

Change-Id: Ide2b356d0944ebde34cc96c6d5a782655bd72288
Signed-off-by: Roger Shimizu <rosh@debian.org>
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/309782
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-07-16 20:11:41 +00:00
927d29a8af Update manifest_name with the returned manifest name for superproject.
This is similar to smart sync, allowing sync to benefit from the patched
manifest.

Bug: [google internal] b/190688390
Change-Id: I158a80afceca606dcd81ec76b2caede369f7ed03
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/312142
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Tested-by: Xin Li <delphij@google.com>
2021-07-14 22:51:33 +00:00
8db30d686a superproject - More friendly user message when superproject failed.
superproject is going to be default for some users. This change
doesn't fail for repo init or repo sync if source couldn't be synced
because of errors in superproject and superproject=true in the config
file. The commands will fail if --use-superproject is specified on
the command line explicitly.

The error messages are logged with trace2 event logs and will be
monitored.

+ sync - When there are errors with superproject and git_superproject
  says it is fatal failure, sync will exit only when --use-superproject
  option is specified on the command line.

+ init - command doesn't fail *if there are any superproject errors),
  but it will print a warning message and logs message via trace2 event
  logs. For fatal errors, init will exit only when --use-superproject
  option is specified on the command line.

+ All git commands log the command that is being executed so trace2
  event logs will know the manifest, remote url and the branch name.

There is no functional change other than fatal errors are honored with
--use-supeproject option with init/sync commands.

Tested the code with the following commands.

$ ./run_tests -v

Test 1 - sync'ing without errors
--------------------------------
Added the following lines to '~/.repoconfig/config
[repo]
	superproject = true

  $ repo_dev init -u https://android.googlesource.com/platform/manifest -b android-s-beta-2
  NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
  repo: error: git fetch call failed, command: git ['fetch', 'https://android.googlesource.com/platform/superproject', '--depth', '1', '--force', '--no-tags', '--filter', 'blob:none', 'android-s-beta-2:android-s-beta-2'], return code: 128, stderr: fatal: couldn't find remote ref android-s-beta-2

  warning: git update of superproject failed, repo sync will not use superproject to fetch source; while this error is not fatal, and you can continue to run repo sync, please run repo init with the --no-use-superproject option to stop seeing this warning

  Your identity is: Raman Tenneti <rtenneti@google.com>
  If you want to change this, please re-run 'repo init' with --config-name

  repo has been initialized in /usr/local/google/home/rtenneti/work/drive2/android/test

$ repo_dev sync
remote: Total 4 (delta 1), reused 4 (delta 1)
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
/usr/local/google/home/rtenneti/work/drive2/android/aosp/.repo/exp-superproject/925043f706ba64db713e9bf3b55987e2-superproject.git: Initial setup for superproject completed.
...

Test 2 - init and sync fail when --use-superproject option is passed
--------------------------------------------------------------------
$ repo_dev init -u https://android.googlesource.com/platform/manifest -b android-s-beta-2 --use-superproject
remote: Total 57 (delta 16), reused 56 (delta 16)
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
repo: error: git fetch call failed, command: git ['fetch', 'https://android.googlesource.com/platform/superproject', '--depth', '1', '--force', '--no-tags', '--filter', 'blob:none', 'android-s-beta-2:android-s-beta-2'], return code: 128, stderr: fatal: couldn't find remote ref android-s-beta-2

warning: git update of superproject failed, repo sync will not use superproject to fetch source; while this error is not fatal, and you can continue to run repo sync, please run repo init with the --no-use-superproject option to stop seeing this warning

rtenneti@rtenneti2:~/work/drive2/android/test$ repo_dev sync --use-superproject
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
repo: error: git fetch call failed, command: git ['fetch', 'https://android.googlesource.com/platform/superproject', '--depth', '1', '--force', '--no-tags', '--filter', 'blob:none', 'android-s-beta-2:android-s-beta-2'], return code: 128, stderr: fatal: couldn't find remote ref android-s-beta-2

warning: Cannot get project commit ids from manifest
warning: Update of revisionId from superproject has failed, repo sync will not use superproject to fetch the source.  Please resync with the --no-use-superproject option to avoid this repo warning.

Test 3 - git fetch command fails and git command is printed
-----------------------------------------------------------
With config change
$ repo_dev init -u https://android.googlesource.com/platform/manifest -b android-s-beta-2
...
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
.../android/test/.repo/exp-superproject/925043f706ba64db713e9bf3b55987e2-superproject.git: Performing initial setup for superproject; this might take several minutes.
repo: error: git fetch call failed,command: git ['fetch', 'https://android.googlesource.com/platform/superproject', '--depth', '1', '--force', '--no-tags', '--filter', 'blob:none', 'android-s-beta-2:android-s-beta-2'], return code: 128, stderr: fatal: couldn't find remote ref android-s-beta-2

warning: git update of superproject failed, repo sync will not use superproject to fetch source; while this error is not fatal and you can continue to run repo sync please run repo init with the --no-use-superproject option to avoid the repo warning

Your identity is: Raman Tenneti <rtenneti@google.com>
If you want to change this, please re-run 'repo init' with --config-name

repo has been initialized in ....

Test 4 - no superproject tag
-----------------------------
$ repo_dev init -u https://android.googlesource.com/platform/manifest -b pie-dev
...
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
repo error: superproject tag is not defined in manifest: .../android/pie_dev/.repo/manifest.xml
warning: git update of superproject failed, repo sync will not use superproject to fetch source; while this error is not fatal and you can continue to run repo sync please run repo init with the --no-use-superproject option to avoid the repo warning

Your identity is: Raman Tenneti <rtenneti@google.com>
If you want to change this, please re-run 'repo init' with --config-name

repo has been initialized in ...

$ repo_dev sync
NOTICE: --use-superproject is in beta; report any issues to the address described in `repo version`
repo error: superproject tag is not defined in manifest: /usr/local/google/home/rtenneti/work/drive2/android/pie_dev/.repo/manifest.xml
warning: Cannot get project commit ids from manifest
warning: Update of revsionId from superproject has failed. Please resync with --no-use-superproject option to avoid the repo warning.

Bug: [google internal] b/192614798
Bug: [google internal] b/Bug: [google internal] b/192614798

Change-Id: I9a97a0e7d9e609fad151bd7dd9cfc523eaa887cd
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/311502
Reviewed-by: Amith Dsouza <amithds@google.com>
Reviewed-by: Xin Li <delphij@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-07-14 00:41:36 +00:00
e39d8b36f6 Fix an issue that repo can't see projects declared in a local manifest.
When loading of superproject failed, we were resetting the manifest to
None, and later code would reload the manifest to see if there are
submodules, which would load the non-local manifest, causing sync with
superproject to fail.

Address this by setting the manifest_name to opt.manifest_name instead.

Bug: [google internal] b/189139268
Change-Id: I3616512e1c4b73e7eca0d83fd1fc474b825adbbf
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/311102
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Xin Li <delphij@google.com>
2021-07-13 23:35:07 +00:00
06da9987f6 Gracefully ignore bad remove-project line
Sometimes, we don't care if the remove project is referring to a
non-existing project and we can just ignore it.  This change allows us
to ignore remove-project entries if the project that they refer to
doesn't exist, making them effectively a no-op.

Because this change breaks existing configuration, we allow this to be
configuration controlled using the `optional` attribute in the
remove-project tag.

Change-Id: I6313a02983e81344eadcb4e47d7d6b037ee7420e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/310964
Tested-by: Michael Kelly <mkelly@arista.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2021-07-08 16:48:21 +00:00
5892973212 sync: dump git output on errors
Bug: https://crbug.com/gerrit/14700
Change-Id: I1ae53dc7f3792b7e8f11d73f706864fb6591eee8
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/311142
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-07-04 02:28:00 +00:00
0cb6e92ac5 Add the ability to administratively enroll repo into using superproject.
Repo will remember a choice and an expiration time of the choice, per
user, about whether to use superproject by default. When not specified
from command line and the choice is not expired, repo would use the
user default value.

When a user default value is not present and when the system wide
enable default is provided in git's system configuration, repo would
ask the user for a confirmation which will be valid for two weeks.

git_config.py: Add support for system config. When reading system
	config, we would use --system to avoid hardcoding a path as the
	value may be different on some other distributions.

git_superproject.py: Add a new subroutine, _UseSuperproject(), which
	returns whether superproject should be used and whether it
	is from a user configuration.

	The value is determined in the following order:

	1. If the user specifies either --use-superproject or
	--no-use-superproject, then that choice is being used.

	2. If neither is specified, we would then check the saved value
	(upon repo init) and use that choice when there was a choice.

	3. We then check if there is a saved and unexpired value for
	user's choice in their ~/.gitconfig, and use the unexpired
	choice, if available.

	4. Finally, if all the above didn't give us a decision, and if
	the git system configuration is providing a rollout hint, present
	a prompt to user for their decision and save it in ~/.gitconfig.

subcmds/sync.py: Make use of the new UseSuperproject() provided by
git_superproject.py.

While there also silent stderr from git describe when determining the
version of repo.

Bug: [google internal] b/190688390
Change-Id: Iad3ee03026342ee500e5d65e2f0fa600d7637613
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/309762
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Xin Li <delphij@google.com>
2021-07-01 16:27:43 +00:00
0e776a5837 Fix an issue when syncing with --use-superproject and clone bundles.
It is possible that a clone bundle contained the object referenced by
the branch in the manifest and in the superproject, but not the branch
itself (for example, the branch may be newly created from an existing
branch, or is not vislble to the user downloading the clone bundle).

When --use-superproject is enabled, because we are overriding
revisionExpr with the SHA1 revision provided by the superproject, the
verification step would succeed, but because the expected branch do not
exist, it would confuse git-repo at a later time, as it is expecting the
remote branch to exist in the local clone.

In project.py, fix this by making SetRevisionId() to always remember
the actual branch name and verify it in _CheckForImmutableRevision()
so that we only skip the fetch step when both objects exists locally.

Bug: [google internal] b/191974277
Change-Id: I49d3ca0667f524c8c45f416492faf95b1dd822fb
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/310802
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Xin Li <delphij@google.com>
2021-06-30 15:31:15 +00:00
1da6f30579 superproject - don't update the commit ids of projects that have revisionId.
Pinned manifests and release manifest have revisionId set for all
projects. For such projects don't update the commit ids.

Tested the code with the following commands.

$ ./run_tests -v

$ repo_dev sync --use-superproject -j8

$ repo_dev sync -n -c -j32 -m $(pwd)/manifest_7482982.xml

Bug: [google internal] b/191995372
Change-Id: I4681135b1d15f4a63527b6f0356d76ec842485d6
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/310582
Reviewed-by: Xin Li <delphij@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
2021-06-29 16:46:07 +00:00
148e1ce81a sync: fix recursive fetching
Commit b2fa30a2b8 ("sync: switch network
fetch to multiprocessing") accidentally changed the variable passed to
the 2nd fetch call from |missing| to |to_fetch| due to a copy & paste
of the earlier changed logic.  Undo that to fix git submodule fetching.

Bug: https://crbug.com/gerrit/14489
Change-Id: I627954f80fd2e80d9d5809b530aa6b0ef9260abb
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/305262
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-05-04 22:43:09 -04:00
32ca6687ae git_config: hoist Windows ssh check earlier
The ssh master logic has never worked under Windows which is why this
code always returned False when running there (including cygwin).  But
the OS check was still done while holding the threading lock.  While
it might be a little slower than necessary, it still worked.

The switch from the threading module to the multiprocessing module
changed global behavior subtly under Windows and broke things: the
globals previously would stay valid, but now they get cleared.  So
the lock is reset to None in children workers.

We could tweak the logic to pass the lock through, but there isn't
much point when the rest of the code is still disabled in Windows.
So perform the platform check before we grab the lock.  This fixes
the crash, and probably speeds things up a few nanoseconds.

This shouldn't be a problem on Linux systems as the platform fork
will duplicate the existing process memory (including globals).

Bug: https://crbug.com/gerrit/14480
Change-Id: I1d1da82c6d7bd6b8cdc1f03f640a520ecd047063
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/305149
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-05-04 19:49:58 -04:00
0ae9503a86 sync: fix print error when handling server error
When converting this logic from print() to the output buffer, this
error codepath should have dropped the use of the file= redirect.

Bug: https://crbug.com/gerrit/14482
Change-Id: Ib484924a2031ba3295c1c1a5b9a2d816b9912279
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/305142
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
2021-05-04 12:48:42 -04:00
d92076d930 Revert "Save cookies back to jar when fetching clone.bundle"
This reverts commit 4abf8e6ef8.

The curl process for updating the cookie file is not atomic.  When
fetching many bundles in parallel, we can sometimes corrupt the file
causing it to be cleared.  Since users should manage gitcookies on
their own, leave it read-only.

Bug: https://crbug.com/gerrit/12300
Change-Id: Id472c99b197bc4cf8533c649f8881509f38643c1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/254092
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
(cherry picked from commit dc1d0e0c7f)
2020-02-11 21:03:35 -05:00
aeb2eee9d3 repo: bump launcher version
This way we can push out the updated stable branch change.

Change-Id: I72d5dab4523a10dfeb6529796892096aa80eba3c
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/254492
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
2020-02-12 00:12:14 +00:00
45d1c372a7 project: fix bytes/str encoding when updating git submodules
Since tempfile.mkstemp() returns a file handle in binary mode,
make sure we turn our strings into bytes before writing.

Bug: https://crbug.com/gerrit/12043
Change-Id: I3e84d595e84b8bc12a1fbc7fd0bb3ea0ba2832b0
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/254393
Reviewed-by: Michael Mortensen <mmortensen@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
(cherry picked from commit 163d42eb43)
2020-02-11 14:46:13 -05:00
19607b2817 repo: allow REPO_REV to be an env var
We do this for REPO_URL already.

Bug: https://crbug.com/gerrit/10233
Change-Id: I53410645474b00d900467c96fa5d8446f3a607d3
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253552
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
(cherry picked from commit 563f1a6512)
2020-02-11 14:44:29 -05:00
68744dbc01 Fixing forall subcommand for Py3
Execution of 'repo forall -p -c' doesn't work with Py3 and ends up
with an error:

Got an error, terminating the pool: TypeError: can only concatenate
str (not "bytes") to str

That's fixed by using the decode() method.

Change-Id: Ice01aaa1822dde8d957b5bf096021dd5a2b7dd51
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253659
Reviewed-by: Mike Frysinger <vapier@google.com>
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Jiri Tyr <jiri.tyr@gmail.com>
(cherry picked from commit 83a3227b62)
2020-02-10 23:31:45 -05:00
ef412624e9 remove spurious +x bits
These files are not directly executable, so drop the +x bits.

Change-Id: Iaf19a03a497686cc21103e7ddf08073173440dd1
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/254076
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
(cherry picked from commit e7c91889a6)
2020-02-10 23:31:03 -05:00
a06ab7d28b find python via env
This allows these scripts to run through the active version of the
virtualenv python when invoked via tox.

Change-Id: Ib52f475b7b20c34d62cfd179a1341da1a08a8b5c
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253974
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
(cherry picked from commit 1b117db767)
2020-02-10 23:30:58 -05:00
471a7ed5f7 git_config: fix encoding handling in GetUrlCookieFile
Make sure we decode the bytes coming from the subprocess.Popen as
we're treating them as strings.

Change-Id: I44100ca5cd94f68a35d489936292eb641006edbe
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253973
Reviewed-by: Jonathan Nieder <jrn@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
(cherry picked from commit ded477dbb9)
2020-02-10 23:28:40 -05:00
619a2b5887 Fix inverted logic around [gitc-]init and -c
Instead of not using '-c' for '--current-branch' when using gitc, we
were only using '-c' when using gitc, so we still had the conflict with
the gitc option, and other users still couldn't use '-c'.

Test: repo init -u https://android.googlesource.com/platform/manifest; repo init -c
Test: repo gitc-init -u ... -b ... -c testing
Change-Id: I71e4950a49c281418249f0783c6a2ea34f0d3e2b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253795
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Dan Willemsen <dwillemsen@google.com>
(cherry picked from commit 93293ca47f)
2020-02-07 15:54:52 -05:00
ab15e42fa4 Do not try to fetch default revision for mirrors always
* Mirrors may contain multiple projects, some of which may not
  always contain the default revision.
* Only fetch the default revision explicitly if
  '--current-branch' is set.
* Fixes breakage casued by
  commit 6856f98467
  "Fix repo mirror with --current-branch"

Bug: https://crbug.com/gerrit/12274
Change-Id: Iaafabe2992f76f3644b841f24245d3e19c9515a9
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253093
Reviewed-by: Kuang-che Wu <kcwu@chromium.org>
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Chirayu Desai <chirayudesai1@gmail.com>
(cherry picked from commit f7b64e3350)
2020-02-06 09:19:35 -05:00
75c02fe4cb init: handle -c conflicts with gitc-init
We keep getting requests for init to support -c.  This conflicts with
gitc-init which allocates -c for its own use.  Lets make this dynamic
so we keep it with "init" but omit it for "gitc-init".

Bug: https://crbug.com/gerrit/10200
Change-Id: Ibf69c2bbeff638e28e63cb08926fea0c622258db
(cherry picked from commit 66098f707a)
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253392
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
2020-02-05 18:04:11 +00:00
afd1b4023f repo: point default branch to repo-1
Since this will be feature-frozen for Python 2 users, lets point the
default update branch to "repo-1" rather than "stable" as the latter
will follow the master development (and Python 3-only).

Bug: https://crbug.com/gerrit/10418
Change-Id: Iceff0983684a580dc5c9ec1c60acfb5eda5ce2c4
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/253172
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
2020-02-05 02:56:08 +00:00
56 changed files with 3989 additions and 370 deletions

View File

@ -24,6 +24,10 @@ from error import InvalidProjectGroupsError
import progress
# Are we generating man-pages?
GENERATE_MANPAGES = os.environ.get('_REPO_GENERATE_MANPAGES_') == ' indeed! '
# Number of projects to submit to a single worker process at a time.
# This number represents a tradeoff between the overhead of IPC and finer
# grained opportunity for parallelism. This particular value was chosen by
@ -122,10 +126,14 @@ class Command(object):
help='only show errors')
if self.PARALLEL_JOBS is not None:
default = 'based on number of CPU cores'
if not GENERATE_MANPAGES:
# Only include active cpu count if we aren't generating man pages.
default = f'%default; {default}'
p.add_option(
'-j', '--jobs',
type=int, default=self.PARALLEL_JOBS,
help='number of jobs to run in parallel (default: %s)' % self.PARALLEL_JOBS)
help=f'number of jobs to run in parallel (default: {default})')
def _Options(self, p):
"""Initialize the option parser with subcommand-specific options."""

View File

@ -14,6 +14,9 @@
# Programmable bash completion. https://github.com/scop/bash-completion
# TODO: Handle interspersed options. We handle `repo h<tab>`, but not
# `repo --time h<tab>`.
# Complete the list of repo subcommands.
__complete_repo_list_commands() {
local repo=${COMP_WORDS[0]}
@ -37,6 +40,7 @@ __complete_repo_list_branches() {
__complete_repo_list_projects() {
local repo=${COMP_WORDS[0]}
"${repo}" list -n 2>/dev/null
"${repo}" list -p --relative-to=. 2>/dev/null
}
# Complete the repo <command> argument.
@ -66,6 +70,48 @@ __complete_repo_command_projects() {
COMPREPLY=($(compgen -W "$(__complete_repo_list_projects)" -- "${current}"))
}
# Complete `repo help`.
__complete_repo_command_help() {
local current=$1
# CWORD=1 is "start".
# CWORD=2 is the <subcommand> which we complete here.
if [[ ${COMP_CWORD} -eq 2 ]]; then
COMPREPLY=(
$(compgen -W "$(__complete_repo_list_commands)" -- "${current}")
)
fi
}
# Complete `repo forall`.
__complete_repo_command_forall() {
local current=$1
# CWORD=1 is "forall".
# CWORD=2+ are <projects> *until* we hit the -c option.
local i
for (( i = 0; i < COMP_CWORD; ++i )); do
if [[ "${COMP_WORDS[i]}" == "-c" ]]; then
return 0
fi
done
COMPREPLY=(
$(compgen -W "$(__complete_repo_list_projects)" -- "${current}")
)
}
# Complete `repo start`.
__complete_repo_command_start() {
local current=$1
# CWORD=1 is "start".
# CWORD=2 is the <branch> which we don't complete.
# CWORD=3+ are <projects> which we complete here.
if [[ ${COMP_CWORD} -gt 2 ]]; then
COMPREPLY=(
$(compgen -W "$(__complete_repo_list_projects)" -- "${current}")
)
fi
}
# Complete the repo subcommand arguments.
__complete_repo_arg() {
if [[ ${COMP_CWORD} -le 1 ]]; then
@ -86,21 +132,8 @@ __complete_repo_arg() {
return 0
;;
help)
if [[ ${COMP_CWORD} -eq 2 ]]; then
COMPREPLY=(
$(compgen -W "$(__complete_repo_list_commands)" -- "${current}")
)
fi
return 0
;;
start)
if [[ ${COMP_CWORD} -gt 2 ]]; then
COMPREPLY=(
$(compgen -W "$(__complete_repo_list_projects)" -- "${current}")
)
fi
help|start|forall)
__complete_repo_command_${command} "${current}"
return 0
;;
@ -118,4 +151,6 @@ __complete_repo() {
return 0
}
complete -F __complete_repo repo
# Fallback to the default complete methods if we aren't able to provide anything
# useful. This will allow e.g. local paths to be used when it makes sense.
complete -F __complete_repo -o bashdefault -o default repo

View File

@ -146,12 +146,18 @@ Instead, you should use standard Git workflows like [git worktree] or
The `.repo/manifests.git/config` file is used to track settings for the entire
repo client checkout.
Most settings use the `[repo]` section to avoid conflicts with git.
Everything under `[repo.syncstate.*]` is used to keep track of sync details for logging
purposes.
User controlled settings are initialized when running `repo init`.
| Setting | `repo init` Option | Use/Meaning |
|------------------- |---------------------------|-------------|
| manifest.groups | `--groups` & `--platform` | The manifest groups to sync |
| manifest.standalone | `--standalone-manifest` | Download manifest as static file instead of creating checkout |
| repo.archive | `--archive` | Use `git archive` for checkouts |
| repo.clonebundle | `--clone-bundle` | Whether the initial sync used clone.bundle explicitly |
| repo.clonefilter | `--clone-filter` | Filter setting when using [partial git clones] |

View File

@ -36,7 +36,7 @@ following DTD:
<!ELEMENT notice (#PCDATA)>
<!ELEMENT remote EMPTY>
<!ELEMENT remote (annotation*)>
<!ATTLIST remote name ID #REQUIRED>
<!ATTLIST remote alias CDATA #IMPLIED>
<!ATTLIST remote fetch CDATA #REQUIRED>
@ -90,20 +90,23 @@ following DTD:
<!ELEMENT extend-project EMPTY>
<!ATTLIST extend-project name CDATA #REQUIRED>
<!ATTLIST extend-project path CDATA #IMPLIED>
<!ATTLIST extend-project dest-path CDATA #IMPLIED>
<!ATTLIST extend-project groups CDATA #IMPLIED>
<!ATTLIST extend-project revision CDATA #IMPLIED>
<!ATTLIST extend-project remote CDATA #IMPLIED>
<!ELEMENT remove-project EMPTY>
<!ATTLIST remove-project name CDATA #REQUIRED>
<!ATTLIST remove-project optional CDATA #IMPLIED>
<!ELEMENT repo-hooks EMPTY>
<!ATTLIST repo-hooks in-project CDATA #REQUIRED>
<!ATTLIST repo-hooks enabled-list CDATA #REQUIRED>
<!ELEMENT superproject EMPTY>
<!ATTLIST superproject name CDATA #REQUIRED>
<!ATTLIST superproject remote IDREF #IMPLIED>
<!ATTLIST superproject name CDATA #REQUIRED>
<!ATTLIST superproject remote IDREF #IMPLIED>
<!ATTLIST superproject revision CDATA #IMPLIED>
<!ELEMENT contactinfo EMPTY>
<!ATTLIST contactinfo bugurl CDATA #REQUIRED>
@ -335,6 +338,11 @@ against changes to the original manifest.
Attribute `path`: If specified, limit the change to projects checked out
at the specified path, rather than all projects with the given name.
Attribute `dest-path`: If specified, a path relative to the top directory
of the repo client where the Git working directory for this project
should be placed. This is used to move a project in the checkout by
overriding the existing `path` setting.
Attribute `groups`: List of additional groups to which this project
belongs. Same syntax as the corresponding element of `project`.
@ -347,12 +355,12 @@ project. Same syntax as the corresponding element of `project`.
### Element annotation
Zero or more annotation elements may be specified as children of a
project element. Each element describes a name-value pair that will be
exported into each project's environment during a 'forall' command,
prefixed with REPO__. In addition, there is an optional attribute
"keep" which accepts the case insensitive values "true" (default) or
"false". This attribute determines whether or not the annotation will
be kept when exported with the manifest subcommand.
project or remote element. Each element describes a name-value pair.
For projects, this name-value pair will be exported into each project's
environment during a 'forall' command, prefixed with `REPO__`. In addition,
there is an optional attribute "keep" which accepts the case insensitive values
"true" (default) or "false". This attribute determines whether or not the
annotation will be kept when exported with the manifest subcommand.
### Element copyfile
@ -393,6 +401,9 @@ This element is mostly useful in a local manifest file, where
the user can remove a project, and possibly replace it with their
own definition.
Attribute `optional`: Set to true to ignore remove-project elements with no
matching `project` element.
### Element repo-hooks
NB: See the [practical documentation](./repo-hooks.md) for using repo hooks.
@ -428,6 +439,11 @@ same meaning as project's name attribute. See the
Attribute `remote`: Name of a previously defined remote element.
If not supplied the remote given by the default element is used.
Attribute `revision`: Name of the Git branch the manifest wants
to track for this superproject. If not supplied the revision given
by the remote element is used if applicable, else the default
element is used.
### Element contactinfo
***

View File

@ -208,80 +208,132 @@ Things in bold indicate stuff to take note of, but does not guarantee that we
still support them.
Things in italics are things we used to care about but probably don't anymore.
| Date | EOL | [Git][rel-g] | [Python][rel-p] | [Ubuntu][rel-u] / [Debian][rel-d] | Git | Python |
|:--------:|:------------:|--------------|-----------------|-----------------------------------|-----|--------|
| Oct 2008 | *Oct 2013* | | 2.6.0 | *10.04 Lucid* - 10.10 Maverick / *Squeeze* |
| Date | EOL | [Git][rel-g] | [Python][rel-p] | [SSH][rel-o] | [Ubuntu][rel-u] / [Debian][rel-d] | Git | Python | SSH |
|:--------:|:------------:|:------------:|:---------------:|:------------:|-----------------------------------|-----|--------|-----|
| Apr 2008 | | | | 5.0 |
| Jun 2008 | | | | 5.1 |
| Oct 2008 | *Oct 2013* | | 2.6.0 | | *10.04 Lucid* - 10.10 Maverick / *Squeeze* |
| Dec 2008 | *Feb 2009* | | 3.0.0 |
| Feb 2009 | *Mar 2012* | | | Debian 5 Lenny | 1.5.6.5 | 2.5.2 |
| Jun 2009 | *Jun 2016* | | 3.1.0 | *10.04 Lucid* - 10.10 Maverick / *Squeeze* |
| Feb 2010 | *Oct 2012* | 1.7.0 | | *10.04 Lucid* - *12.04 Precise* - 12.10 Quantal |
| Apr 2010 | *Apr 2015* | | | *10.04 Lucid* | 1.7.0.4 | 2.6.5 3.1.2 |
| Jul 2010 | *Dec 2019* | | **2.7.0** | 11.04 Natty - **<current>** |
| Oct 2010 | | | | 10.10 Maverick | 1.7.1 | 2.6.6 3.1.3 |
| Feb 2011 | *Feb 2016* | | | Debian 6 Squeeze | 1.7.2.5 | 2.6.6 3.1.3 |
| Apr 2011 | | | | 11.04 Natty | 1.7.4 | 2.7.1 3.2.0 |
| Oct 2011 | *Feb 2016* | | 3.2.0 | 11.04 Natty - 12.10 Quantal |
| Oct 2011 | | | | 11.10 Ocelot | 1.7.5.4 | 2.7.2 3.2.2 |
| Apr 2012 | *Apr 2019* | | | *12.04 Precise* | 1.7.9.5 | 2.7.3 3.2.3 |
| Sep 2012 | *Sep 2017* | | 3.3.0 | 13.04 Raring - 13.10 Saucy |
| Oct 2012 | *Dec 2014* | 1.8.0 | | 13.04 Raring - 13.10 Saucy |
| Oct 2012 | | | | 12.10 Quantal | 1.7.10.4 | 2.7.3 3.2.3 |
| Apr 2013 | | | | 13.04 Raring | 1.8.1.2 | 2.7.4 3.3.1 |
| May 2013 | *May 2018* | | | Debian 7 Wheezy | 1.7.10.4 | 2.7.3 3.2.3 |
| Oct 2013 | | | | 13.10 Saucy | 1.8.3.2 | 2.7.5 3.3.2 |
| Feb 2014 | *Dec 2014* | **1.9.0** | | **14.04 Trusty** |
| Mar 2014 | *Mar 2019* | | **3.4.0** | **14.04 Trusty** - 15.10 Wily / **Jessie** |
| Apr 2014 | **Apr 2022** | | | **14.04 Trusty** | 1.9.1 | 2.7.5 3.4.0 |
| Feb 2009 | | | | 5.2 |
| Feb 2009 | *Mar 2012* | | | | Debian 5 Lenny | 1.5.6.5 | 2.5.2 |
| Jun 2009 | *Jun 2016* | | 3.1.0 | | *10.04 Lucid* - 10.10 Maverick / *Squeeze* |
| Sep 2009 | | | | 5.3 | *10.04 Lucid* |
| Feb 2010 | *Oct 2012* | 1.7.0 | | | *10.04 Lucid* - *12.04 Precise* - 12.10 Quantal |
| Mar 2010 | | | | 5.4 |
| Apr 2010 | | | | 5.5 | 10.10 Maverick |
| Apr 2010 | *Apr 2015* | | | | *10.04 Lucid* | 1.7.0.4 | 2.6.5 3.1.2 | 5.3 |
| Jul 2010 | *Dec 2019* | | *2.7.0* | | 11.04 Natty - *<current>* |
| Aug 2010 | | | | 5.6 |
| Oct 2010 | | | | | 10.10 Maverick | 1.7.1 | 2.6.6 3.1.3 | 5.5 |
| Jan 2011 | | | | 5.7 |
| Feb 2011 | | | | 5.8 | 11.04 Natty |
| Feb 2011 | *Feb 2016* | | | | Debian 6 Squeeze | 1.7.2.5 | 2.6.6 3.1.3 |
| Apr 2011 | | | | | 11.04 Natty | 1.7.4 | 2.7.1 3.2.0 | 5.8 |
| Sep 2011 | | | | 5.9 | *12.04 Precise* |
| Oct 2011 | *Feb 2016* | | 3.2.0 | | 11.04 Natty - 12.10 Quantal |
| Oct 2011 | | | | | 11.10 Ocelot | 1.7.5.4 | 2.7.2 3.2.2 | 5.8 |
| Apr 2012 | | | | 6.0 | 12.10 Quantal |
| Apr 2012 | *Apr 2019* | | | | *12.04 Precise* | 1.7.9.5 | 2.7.3 3.2.3 | 5.9 |
| Aug 2012 | | | | 6.1 | 13.04 Raring |
| Sep 2012 | *Sep 2017* | | 3.3.0 | | 13.04 Raring - 13.10 Saucy |
| Oct 2012 | *Dec 2014* | 1.8.0 | | | 13.04 Raring - 13.10 Saucy |
| Oct 2012 | | | | | 12.10 Quantal | 1.7.10.4 | 2.7.3 3.2.3 | 6.0 |
| Mar 2013 | | | | 6.2 | 13.10 Saucy |
| Apr 2013 | | | | | 13.04 Raring | 1.8.1.2 | 2.7.4 3.3.1 | 6.1 |
| May 2013 | *May 2018* | | | | Debian 7 Wheezy | 1.7.10.4 | 2.7.3 3.2.3 |
| Sep 2013 | | | | 6.3 |
| Oct 2013 | | | | | 13.10 Saucy | 1.8.3.2 | 2.7.5 3.3.2 | 6.2 |
| Nov 2013 | | | | 6.4 |
| Jan 2014 | | | | 6.5 |
| Feb 2014 | *Dec 2014* | **1.9.0** | | | *14.04 Trusty* |
| Mar 2014 | *Mar 2019* | | *3.4.0* | | *14.04 Trusty* - 15.10 Wily / *Jessie* |
| Mar 2014 | | | | 6.6 | *14.04 Trusty* - 14.10 Utopic |
| Apr 2014 | *Apr 2022* | | | | *14.04 Trusty* | 1.9.1 | 2.7.5 3.4.0 | 6.6 |
| May 2014 | *Dec 2014* | 2.0.0 |
| Aug 2014 | *Dec 2014* | **2.1.0** | | 14.10 Utopic - 15.04 Vivid / **Jessie** |
| Oct 2014 | | | | 14.10 Utopic | 2.1.0 | 2.7.8 3.4.2 |
| Aug 2014 | *Dec 2014* | *2.1.0* | | | 14.10 Utopic - 15.04 Vivid / *Jessie* |
| Oct 2014 | | | | 6.7 | 15.04 Vivid |
| Oct 2014 | | | | | 14.10 Utopic | 2.1.0 | 2.7.8 3.4.2 | 6.6 |
| Nov 2014 | *Sep 2015* | 2.2.0 |
| Feb 2015 | *Sep 2015* | 2.3.0 |
| Mar 2015 | | | | 6.8 |
| Apr 2015 | *May 2017* | 2.4.0 |
| Apr 2015 | **Jun 2020** | | | **Debian 8 Jessie** | 2.1.4 | 2.7.9 3.4.2 |
| Apr 2015 | | | | 15.04 Vivid | 2.1.4 | 2.7.9 3.4.3 |
| Jul 2015 | *May 2017* | 2.5.0 | | 15.10 Wily |
| Apr 2015 | *Jun 2020* | | | | *Debian 8 Jessie* | 2.1.4 | 2.7.9 3.4.2 |
| Apr 2015 | | | | | 15.04 Vivid | 2.1.4 | 2.7.9 3.4.3 | 6.7 |
| Jul 2015 | *May 2017* | 2.5.0 | | | 15.10 Wily |
| Jul 2015 | | | | 6.9 | 15.10 Wily |
| Aug 2015 | | | | 7.0 |
| Aug 2015 | | | | 7.1 |
| Sep 2015 | *May 2017* | 2.6.0 |
| Sep 2015 | **Sep 2020** | | **3.5.0** | **16.04 Xenial** - 17.04 Zesty / **Stretch** |
| Oct 2015 | | | | 15.10 Wily | 2.5.0 | 2.7.9 3.4.3 |
| Jan 2016 | *Jul 2017* | **2.7.0** | | **16.04 Xenial** |
| Sep 2015 | *Sep 2020* | | *3.5.0* | | *16.04 Xenial* - 17.04 Zesty / *Stretch* |
| Oct 2015 | | | | | 15.10 Wily | 2.5.0 | 2.7.9 3.4.3 | 6.9 |
| Jan 2016 | *Jul 2017* | *2.7.0* | | | *16.04 Xenial* |
| Feb 2016 | | | | 7.2 | *16.04 Xenial* |
| Mar 2016 | *Jul 2017* | 2.8.0 |
| Apr 2016 | **Apr 2024** | | | **16.04 Xenial** | 2.7.4 | 2.7.11 3.5.1 |
| Jun 2016 | *Jul 2017* | 2.9.0 | | 16.10 Yakkety |
| Apr 2016 | *Apr 2024* | | | | *16.04 Xenial* | 2.7.4 | 2.7.11 3.5.1 | 7.2 |
| Jun 2016 | *Jul 2017* | 2.9.0 | | | 16.10 Yakkety |
| Jul 2016 | | | | 7.3 | 16.10 Yakkety |
| Sep 2016 | *Sep 2017* | 2.10.0 |
| Oct 2016 | | | | 16.10 Yakkety | 2.9.3 | 2.7.11 3.5.1 |
| Nov 2016 | *Sep 2017* | **2.11.0** | | 17.04 Zesty / **Stretch** |
| Dec 2016 | **Dec 2021** | | **3.6.0** | 17.10 Artful - **18.04 Bionic** - 18.10 Cosmic |
| Oct 2016 | | | | | 16.10 Yakkety | 2.9.3 | 2.7.11 3.5.1 | 7.3 |
| Nov 2016 | *Sep 2017* | *2.11.0* | | | 17.04 Zesty / *Stretch* |
| Dec 2016 | **Dec 2021** | | **3.6.0** | | 17.10 Artful - **18.04 Bionic** - 18.10 Cosmic |
| Dec 2016 | | | | 7.4 | 17.04 Zesty / *Debian 9 Stretch* |
| Feb 2017 | *Sep 2017* | 2.12.0 |
| Apr 2017 | | | | 17.04 Zesty | 2.11.0 | 2.7.13 3.5.3 |
| Mar 2017 | | | | 7.5 | 17.10 Artful |
| Apr 2017 | | | | | 17.04 Zesty | 2.11.0 | 2.7.13 3.5.3 | 7.4 |
| May 2017 | *May 2018* | 2.13.0 |
| Jun 2017 | **Jun 2022** | | | **Debian 9 Stretch** | 2.11.0 | 2.7.13 3.5.3 |
| Aug 2017 | *Dec 2019* | 2.14.0 | | 17.10 Artful |
| Jun 2017 | *Jun 2022* | | | | *Debian 9 Stretch* | 2.11.0 | 2.7.13 3.5.3 | 7.4 |
| Aug 2017 | *Dec 2019* | 2.14.0 | | | 17.10 Artful |
| Oct 2017 | *Dec 2019* | 2.15.0 |
| Oct 2017 | | | | 17.10 Artful | 2.14.1 | 2.7.14 3.6.3 |
| Oct 2017 | | | | 7.6 | **18.04 Bionic** |
| Oct 2017 | | | | | 17.10 Artful | 2.14.1 | 2.7.14 3.6.3 | 7.5 |
| Jan 2018 | *Dec 2019* | 2.16.0 |
| Apr 2018 | *Dec 2019* | 2.17.0 | | **18.04 Bionic** |
| Apr 2018 | **Apr 2028** | | | **18.04 Bionic** | 2.17.0 | 2.7.15 3.6.5 |
| Jun 2018 | *Dec 2019* | 2.18.0 |
| Jun 2018 | **Jun 2023** | | 3.7.0 | 19.04 Disco - **20.04 Focal** / **Buster** |
| Sep 2018 | *Dec 2019* | 2.19.0 | | 18.10 Cosmic |
| Oct 2018 | | | | 18.10 Cosmic | 2.19.1 | 2.7.15 3.6.6 |
| Dec 2018 | *Dec 2019* | **2.20.0** | | 19.04 Disco / **Buster** |
| Feb 2019 | *Dec 2019* | 2.21.0 |
| Apr 2019 | | | | 19.04 Disco | 2.20.1 | 2.7.16 3.7.3 |
| Apr 2018 | *Mar 2021* | **2.17.0** | | | **18.04 Bionic** |
| Apr 2018 | | | | 7.7 | 18.10 Cosmic |
| Apr 2018 | **Apr 2028** | | | | **18.04 Bionic** | 2.17.0 | 2.7.15 3.6.5 | 7.6 |
| Jun 2018 | *Mar 2021* | 2.18.0 |
| Jun 2018 | **Jun 2023** | | 3.7.0 | | 19.04 Disco - **20.04 Focal** / **Buster** |
| Aug 2018 | | | | 7.8 |
| Sep 2018 | *Mar 2021* | 2.19.0 | | | 18.10 Cosmic |
| Oct 2018 | | | | 7.9 | 19.04 Disco / **Buster** |
| Oct 2018 | | | | | 18.10 Cosmic | 2.19.1 | 2.7.15 3.6.6 | 7.7 |
| Dec 2018 | *Mar 2021* | **2.20.0** | | | 19.04 Disco - 19.10 Eoan / **Buster** |
| Feb 2019 | *Mar 2021* | 2.21.0 |
| Apr 2019 | | | | 8.0 | 19.10 Eoan |
| Apr 2019 | | | | | 19.04 Disco | 2.20.1 | 2.7.16 3.7.3 | 7.9 |
| Jun 2019 | | 2.22.0 |
| Jul 2019 | **Jul 2024** | | | **Debian 10 Buster** | 2.20.1 | 2.7.16 3.7.3 |
| Aug 2019 | | 2.23.0 |
| Oct 2019 | **Oct 2024** | | 3.8.0 |
| Oct 2019 | | | | 19.10 Eoan | 2.20.1 | 2.7.17 3.7.5 |
| Nov 2019 | | 2.24.0 |
| Jan 2020 | | 2.25.0 | | **20.04 Focal** |
| Apr 2020 | **Apr 2030** | | | **20.04 Focal** | 2.25.0 | 2.7.17 3.7.5 |
| Jul 2019 | **Jul 2024** | | | | **Debian 10 Buster** | 2.20.1 | 2.7.16 3.7.3 | 7.9 |
| Aug 2019 | *Mar 2021* | 2.23.0 |
| Oct 2019 | **Oct 2024** | | 3.8.0 | | **20.04 Focal** - 20.10 Groovy |
| Oct 2019 | | | | 8.1 |
| Oct 2019 | | | | | 19.10 Eoan | 2.20.1 | 2.7.17 3.7.5 | 8.0 |
| Nov 2019 | *Mar 2021* | 2.24.0 |
| Jan 2020 | *Mar 2021* | 2.25.0 | | | **20.04 Focal** |
| Feb 2020 | | | | 8.2 | **20.04 Focal** |
| Mar 2020 | *Mar 2021* | 2.26.0 |
| Apr 2020 | **Apr 2030** | | | | **20.04 Focal** | 2.25.1 | 2.7.17 3.8.2 | 8.2 |
| May 2020 | *Mar 2021* | 2.27.0 | | | 20.10 Groovy |
| May 2020 | | | | 8.3 |
| Jul 2020 | *Mar 2021* | 2.28.0 |
| Sep 2020 | | | | 8.4 | 21.04 Hirsute / **Bullseye** |
| Oct 2020 | *Mar 2021* | 2.29.0 |
| Oct 2020 | | | | | 20.10 Groovy | 2.27.0 | 2.7.18 3.8.6 | 8.3 |
| Oct 2020 | **Oct 2025** | | 3.9.0 | | 21.04 Hirsute / **Bullseye** |
| Dec 2020 | *Mar 2021* | 2.30.0 | | | 21.04 Hirsute / **Bullseye** |
| Mar 2021 | | 2.31.0 |
| Mar 2021 | | | | 8.5 |
| Apr 2021 | | | | 8.6 |
| Apr 2021 | *Jan 2022* | | | | 21.04 Hirsute | 2.30.2 | 2.7.18 3.9.4 | 8.4 |
| Jun 2021 | | 2.32.0 |
| Aug 2021 | | 2.33.0 |
| Aug 2021 | | | | 8.7 |
| Aug 2021 | **Aug 2026** | | | | **Debian 11 Bullseye** | 2.30.2 | 2.7.18 3.9.2 | 8.4 |
| **Date** | **EOL** | **[Git][rel-g]** | **[Python][rel-p]** | **[SSH][rel-o]** | **[Ubuntu][rel-u] / [Debian][rel-d]** | **Git** | **Python** | **SSH** |
[contact]: ../README.md#contact
[rel-d]: https://en.wikipedia.org/wiki/Debian_version_history
[rel-g]: https://en.wikipedia.org/wiki/Git#Releases
[rel-o]: https://www.openssh.com/releasenotes.html
[rel-p]: https://en.wikipedia.org/wiki/History_of_Python#Table_of_versions
[rel-u]: https://en.wikipedia.org/wiki/Ubuntu_version_history#Table_of_versions
[example announcement]: https://groups.google.com/d/topic/repo-discuss/UGBNismWo1M/discussion

41
fetch.py Normal file
View File

@ -0,0 +1,41 @@
# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module contains functions used to fetch files from various sources."""
import subprocess
import sys
from urllib.parse import urlparse
def fetch_file(url):
"""Fetch a file from the specified source using the appropriate protocol.
Returns:
The contents of the file as bytes.
"""
scheme = urlparse(url).scheme
if scheme == 'gs':
cmd = ['gsutil', 'cat', url]
try:
result = subprocess.run(
cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
return result.stdout
except subprocess.CalledProcessError as e:
print('fatal: error running "gsutil": %s' % e.output,
file=sys.stderr)
sys.exit(1)
if scheme == 'file':
with open(url[len('file://'):], 'rb') as f:
return f.read()
raise ValueError('unsupported url %s' % url)

View File

@ -75,7 +75,8 @@ def RepoSourceVersion():
proj = os.path.dirname(os.path.abspath(__file__))
env[GIT_DIR] = os.path.join(proj, '.git')
result = subprocess.run([GIT, 'describe', HEAD], stdout=subprocess.PIPE,
encoding='utf-8', env=env, check=False)
stderr=subprocess.DEVNULL, encoding='utf-8',
env=env, check=False)
if result.returncode == 0:
ver = result.stdout.strip()
if ver.startswith('v'):

View File

@ -13,6 +13,7 @@
# limitations under the License.
import contextlib
import datetime
import errno
from http.client import HTTPException
import json
@ -30,6 +31,10 @@ from repo_trace import Trace
from git_command import GitCommand
from git_refs import R_CHANGES, R_HEADS, R_TAGS
# Prefix that is prepended to all the keys of SyncAnalysisState's data
# that is saved in the config.
SYNC_STATE_PREFIX = 'repo.syncstate.'
ID_RE = re.compile(r'^[0-9a-f]{40}$')
REVIEW_CACHE = dict()
@ -65,6 +70,15 @@ class GitConfig(object):
_USER_CONFIG = '~/.gitconfig'
_ForSystem = None
_SYSTEM_CONFIG = '/etc/gitconfig'
@classmethod
def ForSystem(cls):
if cls._ForSystem is None:
cls._ForSystem = cls(configfile=cls._SYSTEM_CONFIG)
return cls._ForSystem
@classmethod
def ForUser(cls):
if cls._ForUser is None:
@ -90,6 +104,10 @@ class GitConfig(object):
os.path.dirname(self.file),
'.repo_' + os.path.basename(self.file) + '.json')
def ClearCache(self):
"""Clear the in-memory cache of config."""
self._cache_dict = None
def Has(self, name, include_defaults=True):
"""Return true if this configuration file has the key.
"""
@ -253,6 +271,22 @@ class GitConfig(object):
self._branches[b.name] = b
return b
def GetSyncAnalysisStateData(self):
"""Returns data to be logged for the analysis of sync performance."""
return {k: v for k, v in self.DumpConfigDict().items() if k.startswith(SYNC_STATE_PREFIX)}
def UpdateSyncAnalysisState(self, options, superproject_logging_data):
"""Update Config's SYNC_STATE_PREFIX* data with the latest sync data.
Args:
options: Options passed to sync returned from optparse. See _Options().
superproject_logging_data: A dictionary of superproject data that is to be logged.
Returns:
SyncAnalysisState object.
"""
return SyncAnalysisState(self, options, superproject_logging_data)
def GetSubSections(self, section):
"""List all subsection names matching $section.*.*
"""
@ -318,8 +352,8 @@ class GitConfig(object):
Trace(': parsing %s', self.file)
with open(self._json) as fd:
return json.load(fd)
except (IOError, ValueError):
platform_utils.remove(self._json)
except (IOError, ValueErrorl):
platform_utils.remove(self._json, missing_ok=True)
return None
def _SaveJson(self, cache):
@ -327,8 +361,7 @@ class GitConfig(object):
with open(self._json, 'w') as fd:
json.dump(cache, fd, indent=2)
except (IOError, TypeError):
if os.path.exists(self._json):
platform_utils.remove(self._json)
platform_utils.remove(self._json, missing_ok=True)
def _ReadGit(self):
"""
@ -338,9 +371,10 @@ class GitConfig(object):
"""
c = {}
d = self._do('--null', '--list')
if d is None:
if not os.path.exists(self.file):
return c
d = self._do('--null', '--list')
for line in d.rstrip('\0').split('\0'):
if '\n' in line:
key, val = line.split('\n', 1)
@ -356,7 +390,10 @@ class GitConfig(object):
return c
def _do(self, *args):
command = ['config', '--file', self.file, '--includes']
if self.file == self._SYSTEM_CONFIG:
command = ['config', '--system', '--includes']
else:
command = ['config', '--file', self.file, '--includes']
command.extend(args)
p = GitCommand(None,
@ -366,7 +403,7 @@ class GitConfig(object):
if p.Wait() == 0:
return p.stdout
else:
GitError('git config %s: %s' % (str(args), p.stderr))
raise GitError('git config %s: %s' % (str(args), p.stderr))
class RepoConfig(GitConfig):
@ -705,3 +742,70 @@ class Branch(object):
def _Get(self, key, all_keys=False):
key = 'branch.%s.%s' % (self.name, key)
return self._config.GetString(key, all_keys=all_keys)
class SyncAnalysisState:
"""Configuration options related to logging of sync state for analysis.
This object is versioned.
"""
def __init__(self, config, options, superproject_logging_data):
"""Initializes SyncAnalysisState.
Saves the following data into the |config| object.
- sys.argv, options, superproject's logging data.
- repo.*, branch.* and remote.* parameters from config object.
- Current time as synctime.
- Version number of the object.
All the keys saved by this object are prepended with SYNC_STATE_PREFIX.
Args:
config: GitConfig object to store all options.
options: Options passed to sync returned from optparse. See _Options().
superproject_logging_data: A dictionary of superproject data that is to be logged.
"""
self._config = config
now = datetime.datetime.utcnow()
self._Set('main.synctime', now.isoformat() + 'Z')
self._Set('main.version', '1')
self._Set('sys.argv', sys.argv)
for key, value in superproject_logging_data.items():
self._Set(f'superproject.{key}', value)
for key, value in options.__dict__.items():
self._Set(f'options.{key}', value)
config_items = config.DumpConfigDict().items()
EXTRACT_NAMESPACES = {'repo', 'branch', 'remote'}
self._SetDictionary({k: v for k, v in config_items
if not k.startswith(SYNC_STATE_PREFIX) and
k.split('.', 1)[0] in EXTRACT_NAMESPACES})
def _SetDictionary(self, data):
"""Save all key/value pairs of |data| dictionary.
Args:
data: A dictionary whose key/value are to be saved.
"""
for key, value in data.items():
self._Set(key, value)
def _Set(self, key, value):
"""Set the |value| for a |key| in the |_config| member.
|key| is prepended with the value of SYNC_STATE_PREFIX constant.
Args:
key: Name of the key.
value: |value| could be of any type. If it is 'bool', it will be saved
as a Boolean and for all other types, it will be saved as a String.
"""
if value is None:
return
sync_key = f'{SYNC_STATE_PREFIX}{key}'
sync_key = sync_key.replace('_', '')
if isinstance(value, str):
self._config.SetString(sync_key, value)
elif isinstance(value, bool):
self._config.SetBoolean(sync_key, value)
else:
self._config.SetString(sync_key, str(value))

View File

@ -23,11 +23,14 @@ Examples:
"""
import hashlib
import functools
import os
import sys
import time
from typing import NamedTuple
from git_command import git_require, GitCommand
from git_config import RepoConfig
from git_refs import R_HEADS
from manifest_xml import LOCAL_MANIFEST_GROUP_PREFIX
@ -56,7 +59,7 @@ class CommitIdsResult(NamedTuple):
class UpdateProjectsResult(NamedTuple):
"""Return the overriding manifest file and whether caller should exit."""
# Path name of the overriding manfiest file if successful, otherwise None.
# Path name of the overriding manifest file if successful, otherwise None.
manifest_path: str
# Whether the caller should exit.
fatal: bool
@ -70,7 +73,7 @@ class Superproject(object):
is a dictionary with project/commit id entries.
"""
def __init__(self, manifest, repodir, git_event_log,
superproject_dir='exp-superproject', quiet=False):
superproject_dir='exp-superproject', quiet=False, print_messages=False):
"""Initializes superproject.
Args:
@ -80,12 +83,14 @@ class Superproject(object):
git_event_log: A git trace2 event log to log events.
superproject_dir: Relative path under |repodir| to checkout superproject.
quiet: If True then only print the progress messages.
print_messages: if True then print error/warning messages.
"""
self._project_commit_ids = None
self._manifest = manifest
self._git_event_log = git_event_log
self._quiet = quiet
self._branch = self._GetBranch()
self._print_messages = print_messages
self._branch = manifest.branch
self._repodir = os.path.abspath(repodir)
self._superproject_dir = superproject_dir
self._superproject_path = os.path.join(self._repodir, superproject_dir)
@ -93,8 +98,12 @@ class Superproject(object):
_SUPERPROJECT_MANIFEST_NAME)
git_name = ''
if self._manifest.superproject:
remote_name = self._manifest.superproject['remote'].name
git_name = hashlib.md5(remote_name.encode('utf8')).hexdigest() + '-'
remote = self._manifest.superproject['remote']
git_name = hashlib.md5(remote.name.encode('utf8')).hexdigest() + '-'
self._branch = self._manifest.superproject['revision']
self._remote_url = remote.url
else:
self._remote_url = None
self._work_git_name = git_name + _SUPERPROJECT_GIT_NAME
self._work_git = os.path.join(self._superproject_path, self._work_git_name)
@ -103,16 +112,28 @@ class Superproject(object):
"""Returns a dictionary of projects and their commit ids."""
return self._project_commit_ids
def _GetBranch(self):
"""Returns the branch name for getting the approved manifest."""
p = self._manifest.manifestProject
b = p.GetBranch(p.CurrentBranch)
if not b:
return None
branch = b.merge
if branch and branch.startswith(R_HEADS):
branch = branch[len(R_HEADS):]
return branch
@property
def manifest_path(self):
"""Returns the manifest path if the path exists or None."""
return self._manifest_path if os.path.exists(self._manifest_path) else None
def _LogMessage(self, message):
"""Logs message to stderr and _git_event_log."""
if self._print_messages:
print(message, file=sys.stderr)
self._git_event_log.ErrorEvent(message, f'{message}')
def _LogMessagePrefix(self):
"""Returns the prefix string to be logged in each log message"""
return f'repo superproject branch: {self._branch} url: {self._remote_url}'
def _LogError(self, message):
"""Logs error message to stderr and _git_event_log."""
self._LogMessage(f'{self._LogMessagePrefix()} error: {message}')
def _LogWarning(self, message):
"""Logs warning message to stderr and _git_event_log."""
self._LogMessage(f'{self._LogMessagePrefix()} warning: {message}')
def _Init(self):
"""Sets up a local Git repository to get a copy of a superproject.
@ -133,28 +154,25 @@ class Superproject(object):
capture_stderr=True)
retval = p.Wait()
if retval:
print('repo: error: git init call failed with return code: %r, stderr: %r' %
(retval, p.stderr), file=sys.stderr)
self._LogWarning(f'git init call failed, command: git {cmd}, '
f'return code: {retval}, stderr: {p.stderr}')
return False
return True
def _Fetch(self, url):
"""Fetches a local copy of a superproject for the manifest based on url.
Args:
url: superproject's url.
def _Fetch(self):
"""Fetches a local copy of a superproject for the manifest based on |_remote_url|.
Returns:
True if fetch is successful, or False.
"""
if not os.path.exists(self._work_git):
print('git fetch missing drectory: %s' % self._work_git,
file=sys.stderr)
self._LogWarning(f'git fetch missing directory: {self._work_git}')
return False
if not git_require((2, 28, 0)):
print('superproject requires a git version 2.28 or later', file=sys.stderr)
self._LogWarning('superproject requires a git version 2.28 or later')
return False
cmd = ['fetch', url, '--depth', '1', '--force', '--no-tags', '--filter', 'blob:none']
cmd = ['fetch', self._remote_url, '--depth', '1', '--force', '--no-tags',
'--filter', 'blob:none']
if self._branch:
cmd += [self._branch + ':' + self._branch]
p = GitCommand(None,
@ -164,8 +182,8 @@ class Superproject(object):
capture_stderr=True)
retval = p.Wait()
if retval:
print('repo: error: git fetch call failed with return code: %r, stderr: %r' %
(retval, p.stderr), file=sys.stderr)
self._LogWarning(f'git fetch call failed, command: git {cmd}, '
f'return code: {retval}, stderr: {p.stderr}')
return False
return True
@ -178,8 +196,7 @@ class Superproject(object):
data: data returned from 'git ls-tree ...' instead of None.
"""
if not os.path.exists(self._work_git):
print('git ls-tree missing drectory: %s' % self._work_git,
file=sys.stderr)
self._LogWarning(f'git ls-tree missing directory: {self._work_git}')
return None
data = None
branch = 'HEAD' if not self._branch else self._branch
@ -194,8 +211,8 @@ class Superproject(object):
if retval == 0:
data = p.stdout
else:
print('repo: error: git ls-tree call failed with return code: %r, stderr: %r' % (
retval, p.stderr), file=sys.stderr)
self._LogWarning(f'git ls-tree call failed, command: git {cmd}, '
f'return code: {retval}, stderr: {p.stderr}')
return data
def Sync(self):
@ -204,26 +221,22 @@ class Superproject(object):
Returns:
SyncResult
"""
print('NOTICE: --use-superproject is in beta; report any issues to the '
'address described in `repo version`', file=sys.stderr)
if not self._manifest.superproject:
msg = (f'repo error: superproject tag is not defined in manifest: '
f'{self._manifest.manifestFile}')
print(msg, file=sys.stderr)
self._git_event_log.ErrorEvent(msg, '')
self._LogWarning(f'superproject tag is not defined in manifest: '
f'{self._manifest.manifestFile}')
return SyncResult(False, False)
print('NOTICE: --use-superproject is in beta; report any issues to the '
'address described in `repo version`', file=sys.stderr)
should_exit = True
url = self._manifest.superproject['remote'].url
if not url:
print('error: superproject URL is not defined in manifest',
file=sys.stderr)
if not self._remote_url:
self._LogWarning(f'superproject URL is not defined in manifest: '
f'{self._manifest.manifestFile}')
return SyncResult(False, should_exit)
if not self._Init():
return SyncResult(False, should_exit)
if not self._Fetch(url):
if not self._Fetch():
return SyncResult(False, should_exit)
if not self._quiet:
print('%s: Initial setup for superproject completed.' % self._work_git)
@ -241,8 +254,8 @@ class Superproject(object):
data = self._LsTree()
if not data:
print('error: git ls-tree failed to return data for superproject',
file=sys.stderr)
self._LogWarning(f'git ls-tree failed to return data for manifest: '
f'{self._manifest.manifestFile}')
return CommitIdsResult(None, True)
# Parse lines like the following to select lines starting with '160000' and
@ -261,16 +274,14 @@ class Superproject(object):
self._project_commit_ids = commit_ids
return CommitIdsResult(commit_ids, False)
def _WriteManfiestFile(self):
def _WriteManifestFile(self):
"""Writes manifest to a file.
Returns:
manifest_path: Path name of the file into which manifest is written instead of None.
"""
if not os.path.exists(self._superproject_path):
print('error: missing superproject directory %s' %
self._superproject_path,
file=sys.stderr)
self._LogWarning(f'missing superproject directory: {self._superproject_path}')
return None
manifest_str = self._manifest.ToXml(groups=self._manifest.GetGroupsStr()).toxml()
manifest_path = self._manifest_path
@ -278,9 +289,7 @@ class Superproject(object):
with open(manifest_path, 'w', encoding='utf-8') as fp:
fp.write(manifest_str)
except IOError as e:
print('error: cannot write manifest to %s:\n%s'
% (manifest_path, e),
file=sys.stderr)
self._LogError(f'cannot write manifest to : {manifest_path} {e}')
return None
return manifest_path
@ -298,6 +307,9 @@ class Superproject(object):
path = project.relpath
if not path:
return True
# Skip the project with revisionId.
if project.revisionId:
return True
# Skip the project if it comes from the local manifest.
return any(s.startswith(LOCAL_MANIFEST_GROUP_PREFIX) for s in project.groups)
@ -313,7 +325,6 @@ class Superproject(object):
commit_ids_result = self._GetAllProjectsCommitIds()
commit_ids = commit_ids_result.commit_ids
if not commit_ids:
print('error: Cannot get project commit ids from manifest', file=sys.stderr)
return UpdateProjectsResult(None, commit_ids_result.fatal)
projects_missing_commit_ids = []
@ -328,15 +339,77 @@ class Superproject(object):
# If superproject doesn't have a commit id for a project, then report an
# error event and continue as if do not use superproject is specified.
if projects_missing_commit_ids:
msg = (f'error: please file a bug using {self._manifest.contactinfo.bugurl} '
f'to report missing commit_ids for: {projects_missing_commit_ids}')
print(msg, file=sys.stderr)
self._git_event_log.ErrorEvent(msg, '')
self._LogWarning(f'please file a bug using {self._manifest.contactinfo.bugurl} '
f'to report missing commit_ids for: {projects_missing_commit_ids}')
return UpdateProjectsResult(None, False)
for project in projects:
if not self._SkipUpdatingProjectRevisionId(project):
project.SetRevisionId(commit_ids.get(project.relpath))
manifest_path = self._WriteManfiestFile()
manifest_path = self._WriteManifestFile()
return UpdateProjectsResult(manifest_path, False)
@functools.lru_cache(maxsize=None)
def _UseSuperprojectFromConfiguration():
"""Returns the user choice of whether to use superproject."""
user_cfg = RepoConfig.ForUser()
time_now = int(time.time())
user_value = user_cfg.GetBoolean('repo.superprojectChoice')
if user_value is not None:
user_expiration = user_cfg.GetInt('repo.superprojectChoiceExpire')
if user_expiration is None or user_expiration <= 0 or user_expiration >= time_now:
# TODO(b/190688390) - Remove prompt when we are comfortable with the new
# default value.
if user_value:
print(('You are currently enrolled in Git submodules experiment '
'(go/android-submodules-quickstart). Use --no-use-superproject '
'to override.\n'), file=sys.stderr)
else:
print(('You are not currently enrolled in Git submodules experiment '
'(go/android-submodules-quickstart). Use --use-superproject '
'to override.\n'), file=sys.stderr)
return user_value
# We don't have an unexpired choice, ask for one.
system_cfg = RepoConfig.ForSystem()
system_value = system_cfg.GetBoolean('repo.superprojectChoice')
if system_value:
# The system configuration is proposing that we should enable the
# use of superproject. Treat the user as enrolled for two weeks.
#
# TODO(b/190688390) - Remove prompt when we are comfortable with the new
# default value.
userchoice = True
time_choiceexpire = time_now + (86400 * 14)
user_cfg.SetString('repo.superprojectChoiceExpire', str(time_choiceexpire))
user_cfg.SetBoolean('repo.superprojectChoice', userchoice)
print('You are automatically enrolled in Git submodules experiment '
'(go/android-submodules-quickstart) for another two weeks.\n',
file=sys.stderr)
return True
# For all other cases, we would not use superproject by default.
return False
def PrintMessages(opt, manifest):
"""Returns a boolean if error/warning messages are to be printed."""
return opt.use_superproject is not None or manifest.superproject
def UseSuperproject(opt, manifest):
"""Returns a boolean if use-superproject option is enabled."""
if opt.use_superproject is not None:
return opt.use_superproject
else:
client_value = manifest.manifestProject.config.GetBoolean('repo.superproject')
if client_value is not None:
return client_value
else:
if not manifest.superproject:
return False
return _UseSuperprojectFromConfiguration()

View File

@ -144,6 +144,19 @@ class EventLog(object):
command_event['subcommands'] = subcommands
self._log.append(command_event)
def LogConfigEvents(self, config, event_dict_name):
"""Append a |event_dict_name| event for each config key in |config|.
Args:
config: Configuration dictionary.
event_dict_name: Name of the event dictionary for items to be logged under.
"""
for param, value in config.items():
event = self._CreateEventDict(event_dict_name)
event['param'] = param
event['value'] = value
self._log.append(event)
def DefParamRepoEvents(self, config):
"""Append a 'def_param' event for each repo.* config key to the current log.
@ -152,12 +165,27 @@ class EventLog(object):
"""
# Only output the repo.* config parameters.
repo_config = {k: v for k, v in config.items() if k.startswith('repo.')}
self.LogConfigEvents(repo_config, 'def_param')
for param, value in repo_config.items():
def_param_event = self._CreateEventDict('def_param')
def_param_event['param'] = param
def_param_event['value'] = value
self._log.append(def_param_event)
def GetDataEventName(self, value):
"""Returns 'data-json' if the value is an array else returns 'data'."""
return 'data-json' if value[0] == '[' and value[-1] == ']' else 'data'
def LogDataConfigEvents(self, config, prefix):
"""Append a 'data' event for each config key/value in |config| to the current log.
For each keyX and valueX of the config, "key" field of the event is '|prefix|/keyX'
and the "value" of the "key" field is valueX.
Args:
config: Configuration dictionary.
prefix: Prefix for each key that is logged.
"""
for key, value in config.items():
event = self._CreateEventDict(self.GetDataEventName(value))
event['key'] = f'{prefix}/{key}'
event['value'] = value
self._log.append(event)
def ErrorEvent(self, msg, fmt):
"""Append a 'error' event to the current log."""

73
main.py
View File

@ -95,6 +95,8 @@ global_options = optparse.OptionParser(
add_help_option=False)
global_options.add_option('-h', '--help', action='store_true',
help='show this help message and exit')
global_options.add_option('--help-all', action='store_true',
help='show this help message with all subcommands and exit')
global_options.add_option('-p', '--paginate',
dest='pager', action='store_true',
help='display command output in the pager')
@ -116,6 +118,10 @@ global_options.add_option('--time',
global_options.add_option('--version',
dest='show_version', action='store_true',
help='display this version of repo')
global_options.add_option('--show-toplevel',
action='store_true',
help='display the path of the top-level directory of '
'the repo client checkout')
global_options.add_option('--event-log',
dest='event_log', action='store',
help='filename of event log to append timeline to')
@ -128,34 +134,40 @@ class _Repo(object):
self.repodir = repodir
self.commands = all_commands
def _PrintHelp(self, short: bool = False, all_commands: bool = False):
"""Show --help screen."""
global_options.print_help()
print()
if short:
commands = ' '.join(sorted(self.commands))
wrapped_commands = textwrap.wrap(commands, width=77)
print('Available commands:\n %s' % ('\n '.join(wrapped_commands),))
print('\nRun `repo help <command>` for command-specific details.')
print('Bug reports:', Wrapper().BUG_URL)
else:
cmd = self.commands['help']()
if all_commands:
cmd.PrintAllCommandsBody()
else:
cmd.PrintCommonCommandsBody()
def _ParseArgs(self, argv):
"""Parse the main `repo` command line options."""
name = None
glob = []
for i in range(len(argv)):
if not argv[i].startswith('-'):
name = argv[i]
if i > 0:
glob = argv[:i]
for i, arg in enumerate(argv):
if not arg.startswith('-'):
name = arg
glob = argv[:i]
argv = argv[i + 1:]
break
if not name:
else:
name = None
glob = argv
name = 'help'
argv = []
gopts, _gargs = global_options.parse_args(glob)
name, alias_args = self._ExpandAlias(name)
argv = alias_args + argv
if gopts.help:
global_options.print_help()
commands = ' '.join(sorted(self.commands))
wrapped_commands = textwrap.wrap(commands, width=77)
print('\nAvailable commands:\n %s' % ('\n '.join(wrapped_commands),))
print('\nRun `repo help <command>` for command-specific details.')
global_options.exit()
if name:
name, alias_args = self._ExpandAlias(name)
argv = alias_args + argv
return (name, gopts, argv)
@ -186,12 +198,21 @@ class _Repo(object):
if gopts.trace:
SetTrace()
if gopts.show_version:
if name == 'help':
name = 'version'
else:
print('fatal: invalid usage of --version', file=sys.stderr)
return 1
# Handle options that terminate quickly first.
if gopts.help or gopts.help_all:
self._PrintHelp(short=False, all_commands=gopts.help_all)
return 0
elif gopts.show_version:
# Always allow global --version regardless of subcommand validity.
name = 'version'
elif gopts.show_toplevel:
print(os.path.dirname(self.repodir))
return 0
elif not name:
# No subcommand specified, so show the help/subcommand.
self._PrintHelp(short=True)
return 1
SetDefaultColoring(gopts.color)

36
man/repo-abandon.1 Normal file
View File

@ -0,0 +1,36 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo abandon" "Repo Manual"
.SH NAME
repo \- repo abandon - manual page for repo abandon
.SH SYNOPSIS
.B repo
\fI\,abandon \/\fR[\fI\,--all | <branchname>\/\fR] [\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Permanently abandon a development branch
.PP
This subcommand permanently abandons a development branch by
deleting it (and all its history) from your local repository.
.PP
It is equivalent to "git branch \fB\-D\fR <branchname>".
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-\-all\fR
delete all branches in all projects
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help abandon` to view the detailed manual.

1
man/repo-branch.1 Normal file
View File

@ -0,0 +1 @@
.so man1/repo-branches.1

59
man/repo-branches.1 Normal file
View File

@ -0,0 +1,59 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo branches" "Repo Manual"
.SH NAME
repo \- repo branches - manual page for repo branches
.SH SYNOPSIS
.B repo
\fI\,branches \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
View current topic branches
.PP
Summarizes the currently available topic branches.
.PP
# Branch Display
.PP
The branch display output by this command is organized into four
columns of information; for example:
.TP
*P nocolor
| in repo
.TP
repo2
|
.PP
The first column contains a * if the branch is the currently
checked out branch in any of the specified projects, or a blank
if no project has the branch checked out.
.PP
The second column contains either blank, p or P, depending upon
the upload status of the branch.
.IP
(blank): branch not yet published by repo upload
.IP
P: all commits were published by repo upload
p: only some commits were published by repo upload
.PP
The third column contains the branch name.
.PP
The fourth column (after the | separator) lists the projects that
the branch appears in, or does not appear in. If no project list
is shown, then the branch appears in all projects.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help branches` to view the detailed manual.

36
man/repo-checkout.1 Normal file
View File

@ -0,0 +1,36 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo checkout" "Repo Manual"
.SH NAME
repo \- repo checkout - manual page for repo checkout
.SH SYNOPSIS
.B repo
\fI\,checkout <branchname> \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Checkout a branch for development
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help checkout` to view the detailed manual.
.SH DETAILS
.PP
The 'repo checkout' command checks out an existing branch that was previously
created by 'repo start'.
.PP
The command is equivalent to:
.IP
repo forall [<project>...] \fB\-c\fR git checkout <branchname>

28
man/repo-cherry-pick.1 Normal file
View File

@ -0,0 +1,28 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo cherry-pick" "Repo Manual"
.SH NAME
repo \- repo cherry-pick - manual page for repo cherry-pick
.SH SYNOPSIS
.B repo
\fI\,cherry-pick <sha1>\/\fR
.SH DESCRIPTION
Summary
.PP
Cherry\-pick a change.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help cherry\-pick` to view the detailed manual.
.SH DETAILS
.PP
\&'repo cherry\-pick' cherry\-picks a change from one branch to another. The change
id will be updated, and a reference to the old change id will be added.

35
man/repo-diff.1 Normal file
View File

@ -0,0 +1,35 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo diff" "Repo Manual"
.SH NAME
repo \- repo diff - manual page for repo diff
.SH SYNOPSIS
.B repo
\fI\,diff \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Show changes between commit and working tree
.PP
The \fB\-u\fR option causes 'repo diff' to generate diff output with file paths
relative to the repository root, so the output can be applied
to the Unix 'patch' command.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-u\fR, \fB\-\-absolute\fR
paths are relative to the repository root
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help diff` to view the detailed manual.

61
man/repo-diffmanifests.1 Normal file
View File

@ -0,0 +1,61 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo diffmanifests" "Repo Manual"
.SH NAME
repo \- repo diffmanifests - manual page for repo diffmanifests
.SH SYNOPSIS
.B repo
\fI\,diffmanifests manifest1.xml \/\fR[\fI\,manifest2.xml\/\fR] [\fI\,options\/\fR]
.SH DESCRIPTION
Summary
.PP
Manifest diff utility
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-\-raw\fR
display raw diff
.TP
\fB\-\-no\-color\fR
does not display the diff in color
.TP
\fB\-\-pretty\-format=\fR<FORMAT>
print the log using a custom git pretty format string
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help diffmanifests` to view the detailed manual.
.SH DETAILS
.PP
The repo diffmanifests command shows differences between project revisions of
manifest1 and manifest2. if manifest2 is not specified, current manifest.xml
will be used instead. Both absolute and relative paths may be used for
manifests. Relative paths start from project's ".repo/manifests" folder.
.PP
The \fB\-\-raw\fR option Displays the diff in a way that facilitates parsing, the
project pattern will be <status> <path> <revision from> [<revision to>] and the
commit pattern will be <status> <onelined log> with status values respectively :
.IP
A = Added project
R = Removed project
C = Changed project
U = Project with unreachable revision(s) (revision(s) not found)
.PP
for project, and
.IP
A = Added commit
R = Removed commit
.PP
for a commit.
.PP
Only changed projects may contain commits, and commit status always starts with
a space, and are part of last printed project. Unreachable revisions may occur
if project is not up to date or if repo has not been initialized with all the
groups, in which case some projects won't be synced and their revisions won't be
found.

44
man/repo-download.1 Normal file
View File

@ -0,0 +1,44 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo download" "Repo Manual"
.SH NAME
repo \- repo download - manual page for repo download
.SH SYNOPSIS
.B repo
\fI\,download {\/\fR[\fI\,project\/\fR] \fI\,change\/\fR[\fI\,/patchset\/\fR]\fI\,}\/\fR...
.SH DESCRIPTION
Summary
.PP
Download and checkout a change
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-b\fR BRANCH, \fB\-\-branch\fR=\fI\,BRANCH\/\fR
create a new branch first
.TP
\fB\-c\fR, \fB\-\-cherry\-pick\fR
cherry\-pick instead of checkout
.TP
\fB\-x\fR, \fB\-\-record\-origin\fR
pass \fB\-x\fR when cherry\-picking
.TP
\fB\-r\fR, \fB\-\-revert\fR
revert instead of checkout
.TP
\fB\-f\fR, \fB\-\-ff\-only\fR
force fast\-forward merge
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help download` to view the detailed manual.
.SH DETAILS
.PP
The 'repo download' command downloads a change from the review system and makes
it available in your project's local working directory. If no project is
specified try to use current directory as a project.

128
man/repo-forall.1 Normal file
View File

@ -0,0 +1,128 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo forall" "Repo Manual"
.SH NAME
repo \- repo forall - manual page for repo forall
.SH SYNOPSIS
.B repo
\fI\,forall \/\fR[\fI\,<project>\/\fR...] \fI\,-c <command> \/\fR[\fI\,<arg>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Run a shell command in each project
.PP
repo forall \fB\-r\fR str1 [str2] ... \fB\-c\fR <command> [<arg>...]
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-r\fR, \fB\-\-regex\fR
execute the command only on projects matching regex or
wildcard expression
.TP
\fB\-i\fR, \fB\-\-inverse\-regex\fR
execute the command only on projects not matching
regex or wildcard expression
.TP
\fB\-g\fR GROUPS, \fB\-\-groups\fR=\fI\,GROUPS\/\fR
execute the command only on projects matching the
specified groups
.TP
\fB\-c\fR, \fB\-\-command\fR
command (and arguments) to execute
.TP
\fB\-e\fR, \fB\-\-abort\-on\-errors\fR
abort if a command exits unsuccessfully
.TP
\fB\-\-ignore\-missing\fR
silently skip & do not exit non\-zero due missing
checkouts
.TP
\fB\-\-interactive\fR
force interactive usage
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.TP
\fB\-p\fR
show project headers before output
.PP
Run `repo help forall` to view the detailed manual.
.SH DETAILS
.PP
Executes the same shell command in each project.
.PP
The \fB\-r\fR option allows running the command only on projects matching regex or
wildcard expression.
.PP
By default, projects are processed non\-interactively in parallel. If you want to
run interactive commands, make sure to pass \fB\-\-interactive\fR to force \fB\-\-jobs\fR 1.
While the processing order of projects is not guaranteed, the order of project
output is stable.
.PP
Output Formatting
.PP
The \fB\-p\fR option causes 'repo forall' to bind pipes to the command's stdin, stdout
and stderr streams, and pipe all output into a continuous stream that is
displayed in a single pager session. Project headings are inserted before the
output of each command is displayed. If the command produces no output in a
project, no heading is displayed.
.PP
The formatting convention used by \fB\-p\fR is very suitable for some types of
searching, e.g. `repo forall \fB\-p\fR \fB\-c\fR git log \fB\-SFoo\fR` will print all commits that
add or remove references to Foo.
.PP
The \fB\-v\fR option causes 'repo forall' to display stderr messages if a command
produces output only on stderr. Normally the \fB\-p\fR option causes command output to
be suppressed until the command produces at least one byte of output on stdout.
.PP
Environment
.PP
pwd is the project's working directory. If the current client is a mirror
client, then pwd is the Git repository.
.PP
REPO_PROJECT is set to the unique name of the project.
.PP
REPO_PATH is the path relative the the root of the client.
.PP
REPO_REMOTE is the name of the remote system from the manifest.
.PP
REPO_LREV is the name of the revision from the manifest, translated to a local
tracking branch. If you need to pass the manifest revision to a locally executed
git command, use REPO_LREV.
.PP
REPO_RREV is the name of the revision from the manifest, exactly as written in
the manifest.
.PP
REPO_COUNT is the total number of projects being iterated.
.PP
REPO_I is the current (1\-based) iteration count. Can be used in conjunction with
REPO_COUNT to add a simple progress indicator to your command.
.PP
REPO__* are any extra environment variables, specified by the "annotation"
element under any project element. This can be useful for differentiating trees
based on user\-specific criteria, or simply annotating tree details.
.PP
shell positional arguments ($1, $2, .., $#) are set to any arguments following
<command>.
.PP
Example: to list projects:
.IP
repo forall \fB\-c\fR 'echo $REPO_PROJECT'
.PP
Notice that $REPO_PROJECT is quoted to ensure it is expanded in the context of
running <command> instead of in the calling shell.
.PP
Unless \fB\-p\fR is used, stdin, stdout, stderr are inherited from the terminal and are
not redirected.
.PP
If \fB\-e\fR is used, when a command exits unsuccessfully, 'repo forall' will abort
without iterating through the remaining projects.

31
man/repo-gitc-delete.1 Normal file
View File

@ -0,0 +1,31 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo gitc-delete" "Repo Manual"
.SH NAME
repo \- repo gitc-delete - manual page for repo gitc-delete
.SH SYNOPSIS
.B repo
\fI\,gitc-delete\/\fR
.SH DESCRIPTION
Summary
.PP
Delete a GITC Client.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-f\fR, \fB\-\-force\fR
force the deletion (no prompt)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help gitc\-delete` to view the detailed manual.
.SH DETAILS
.PP
This subcommand deletes the current GITC client, deleting the GITC manifest and
all locally downloaded sources.

150
man/repo-gitc-init.1 Normal file
View File

@ -0,0 +1,150 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "September 2021" "repo gitc-init" "Repo Manual"
.SH NAME
repo \- repo gitc-init - manual page for repo gitc-init
.SH SYNOPSIS
.B repo
\fI\,gitc-init \/\fR[\fI\,options\/\fR] [\fI\,client name\/\fR]
.SH DESCRIPTION
Summary
.PP
Initialize a GITC Client.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS Manifest options:
.TP
\fB\-u\fR URL, \fB\-\-manifest\-url\fR=\fI\,URL\/\fR
manifest repository location
.TP
\fB\-b\fR REVISION, \fB\-\-manifest\-branch\fR=\fI\,REVISION\/\fR
manifest branch or revision (use HEAD for default)
.TP
\fB\-m\fR NAME.xml, \fB\-\-manifest\-name\fR=\fI\,NAME\/\fR.xml
initial manifest file
.TP
\fB\-\-standalone\-manifest\fR
download the manifest as a static file rather then
create a git checkout of the manifest repo
.TP
\fB\-g\fR GROUP, \fB\-\-groups\fR=\fI\,GROUP\/\fR
restrict manifest projects to ones with specified
group(s) [default|all|G1,G2,G3|G4,\-G5,\-G6]
.TP
\fB\-p\fR PLATFORM, \fB\-\-platform\fR=\fI\,PLATFORM\/\fR
restrict manifest projects to ones with a specified
platform group [auto|all|none|linux|darwin|...]
.TP
\fB\-\-submodules\fR
sync any submodules associated with the manifest repo
.SS Manifest (only) checkout options:
.TP
\fB\-\-current\-branch\fR
fetch only current manifest branch from server
.TP
\fB\-\-no\-current\-branch\fR
fetch all manifest branches from server
.TP
\fB\-\-tags\fR
fetch tags in the manifest
.TP
\fB\-\-no\-tags\fR
don't fetch tags in the manifest
.SS Checkout modes:
.TP
\fB\-\-mirror\fR
create a replica of the remote repositories rather
than a client working directory
.TP
\fB\-\-archive\fR
checkout an archive instead of a git repository for
each project. See git archive.
.TP
\fB\-\-worktree\fR
use git\-worktree to manage projects
.SS Project checkout optimizations:
.TP
\fB\-\-reference\fR=\fI\,DIR\/\fR
location of mirror directory
.TP
\fB\-\-dissociate\fR
dissociate from reference mirrors after clone
.TP
\fB\-\-depth\fR=\fI\,DEPTH\/\fR
create a shallow clone with given depth; see git clone
.TP
\fB\-\-partial\-clone\fR
perform partial clone (https://gitscm.com/docs/gitrepositorylayout#_code_partialclone_code)
.TP
\fB\-\-no\-partial\-clone\fR
disable use of partial clone (https://gitscm.com/docs/gitrepositorylayout#_code_partialclone_code)
.TP
\fB\-\-partial\-clone\-exclude\fR=\fI\,PARTIAL_CLONE_EXCLUDE\/\fR
exclude the specified projects (a comma\-delimited
project names) from partial clone (https://gitscm.com/docs/gitrepositorylayout#_code_partialclone_code)
.TP
\fB\-\-clone\-filter\fR=\fI\,CLONE_FILTER\/\fR
filter for use with \fB\-\-partial\-clone\fR [default:
blob:none]
.TP
\fB\-\-use\-superproject\fR
use the manifest superproject to sync projects
.TP
\fB\-\-no\-use\-superproject\fR
disable use of manifest superprojects
.TP
\fB\-\-clone\-bundle\fR
enable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
not \fB\-\-partial\-clone\fR)
.TP
\fB\-\-no\-clone\-bundle\fR
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
\fB\-\-partial\-clone\fR)
.SS repo Version options:
.TP
\fB\-\-repo\-url\fR=\fI\,URL\/\fR
repo repository location ($REPO_URL)
.TP
\fB\-\-repo\-rev\fR=\fI\,REV\/\fR
repo branch or revision ($REPO_REV)
.TP
\fB\-\-no\-repo\-verify\fR
do not verify repo source code
.SS Other options:
.TP
\fB\-\-config\-name\fR
Always prompt for name/e\-mail
.SS GITC options:
.TP
\fB\-f\fR MANIFEST_FILE, \fB\-\-manifest\-file\fR=\fI\,MANIFEST_FILE\/\fR
Optional manifest file to use for this GITC client.
.TP
\fB\-c\fR GITC_CLIENT, \fB\-\-gitc\-client\fR=\fI\,GITC_CLIENT\/\fR
Name of the gitc_client instance to create or modify.
.PP
Run `repo help gitc\-init` to view the detailed manual.
.SH DETAILS
.PP
The 'repo gitc\-init' command is ran to initialize a new GITC client for use with
the GITC file system.
.PP
This command will setup the client directory, initialize repo, just like repo
init does, and then downloads the manifest collection and installs it in the
\&.repo/directory of the GITC client.
.PP
Once this is done, a GITC manifest is generated by pulling the HEAD SHA for each
project and generates the properly formatted XML file and installs it as
\&.manifest in the GITC client directory.
.PP
The \fB\-c\fR argument is required to specify the GITC client name.
.PP
The optional \fB\-f\fR argument can be used to specify the manifest file to use for
this GITC client.

119
man/repo-grep.1 Normal file
View File

@ -0,0 +1,119 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo grep" "Repo Manual"
.SH NAME
repo \- repo grep - manual page for repo grep
.SH SYNOPSIS
.B repo
\fI\,grep {pattern | -e pattern} \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Print lines matching a pattern
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.SS Logging options:
.TP
\fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS Sources:
.TP
\fB\-\-cached\fR
Search the index, instead of the work tree
.TP
\fB\-r\fR TREEish, \fB\-\-revision\fR=\fI\,TREEish\/\fR
Search TREEish, instead of the work tree
.SS Pattern:
.TP
\fB\-e\fR PATTERN
Pattern to search for
.TP
\fB\-i\fR, \fB\-\-ignore\-case\fR
Ignore case differences
.TP
\fB\-a\fR, \fB\-\-text\fR
Process binary files as if they were text
.TP
\fB\-I\fR
Don't match the pattern in binary files
.TP
\fB\-w\fR, \fB\-\-word\-regexp\fR
Match the pattern only at word boundaries
.TP
\fB\-v\fR, \fB\-\-invert\-match\fR
Select non\-matching lines
.TP
\fB\-G\fR, \fB\-\-basic\-regexp\fR
Use POSIX basic regexp for patterns (default)
.TP
\fB\-E\fR, \fB\-\-extended\-regexp\fR
Use POSIX extended regexp for patterns
.TP
\fB\-F\fR, \fB\-\-fixed\-strings\fR
Use fixed strings (not regexp) for pattern
.SS Pattern Grouping:
.TP
\fB\-\-all\-match\fR
Limit match to lines that have all patterns
.TP
\fB\-\-and\fR, \fB\-\-or\fR, \fB\-\-not\fR
Boolean operators to combine patterns
.TP
\-(, \-)
Boolean operator grouping
.SS Output:
.TP
\fB\-n\fR
Prefix the line number to matching lines
.TP
\fB\-C\fR CONTEXT
Show CONTEXT lines around match
.TP
\fB\-B\fR CONTEXT
Show CONTEXT lines before match
.TP
\fB\-A\fR CONTEXT
Show CONTEXT lines after match
.TP
\fB\-l\fR, \fB\-\-name\-only\fR, \fB\-\-files\-with\-matches\fR
Show only file names containing matching lines
.TP
\fB\-L\fR, \fB\-\-files\-without\-match\fR
Show only file names not containing matching lines
.PP
Run `repo help grep` to view the detailed manual.
.SH DETAILS
.PP
Search for the specified patterns in all project files.
.PP
Boolean Options
.PP
The following options can appear as often as necessary to express the pattern to
locate:
.HP
\fB\-e\fR PATTERN
.HP
\fB\-\-and\fR, \fB\-\-or\fR, \fB\-\-not\fR, \-(, \-)
.PP
Further, the \fB\-r\fR/\-\-revision option may be specified multiple times in order to
scan multiple trees. If the same file matches in more than one tree, only the
first result is reported, prefixed by the revision name it was found under.
.PP
Examples
.PP
Look for a line that has '#define' and either 'MAX_PATH or 'PATH_MAX':
.IP
repo grep \fB\-e\fR '#define' \fB\-\-and\fR \-\e( \fB\-e\fR MAX_PATH \fB\-e\fR PATH_MAX \e)
.PP
Look for a line that has 'NODE' or 'Unexpected' in files that contain a line
that matches both expressions:
.IP
repo grep \fB\-\-all\-match\fR \fB\-e\fR NODE \fB\-e\fR Unexpected

33
man/repo-help.1 Normal file
View File

@ -0,0 +1,33 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo help" "Repo Manual"
.SH NAME
repo \- repo help - manual page for repo help
.SH SYNOPSIS
.B repo
\fI\,help \/\fR[\fI\,--all|command\/\fR]
.SH DESCRIPTION
Summary
.PP
Display detailed help on a command
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-a\fR, \fB\-\-all\fR
show the complete list of commands
.TP
\fB\-\-help\-all\fR
show the \fB\-\-help\fR of all commands
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help help` to view the detailed manual.
.SH DETAILS
.PP
Displays detailed usage information about a command.

40
man/repo-info.1 Normal file
View File

@ -0,0 +1,40 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo info" "Repo Manual"
.SH NAME
repo \- repo info - manual page for repo info
.SH SYNOPSIS
.B repo
\fI\,info \/\fR[\fI\,-dl\/\fR] [\fI\,-o \/\fR[\fI\,-c\/\fR]] [\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Get info on the manifest branch, current branch or unmerged branches
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-d\fR, \fB\-\-diff\fR
show full info and commit diff including remote
branches
.TP
\fB\-o\fR, \fB\-\-overview\fR
show overview of all local commits
.TP
\fB\-c\fR, \fB\-\-current\-branch\fR
consider only checked out branches
.TP
\fB\-\-no\-current\-branch\fR
consider all local branches
.TP
\fB\-l\fR, \fB\-\-local\-only\fR
disable all remote operations
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help info` to view the detailed manual.

170
man/repo-init.1 Normal file
View File

@ -0,0 +1,170 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "September 2021" "repo init" "Repo Manual"
.SH NAME
repo \- repo init - manual page for repo init
.SH SYNOPSIS
.B repo
\fI\,init \/\fR[\fI\,options\/\fR] [\fI\,manifest url\/\fR]
.SH DESCRIPTION
Summary
.PP
Initialize a repo client checkout in the current directory
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS Manifest options:
.TP
\fB\-u\fR URL, \fB\-\-manifest\-url\fR=\fI\,URL\/\fR
manifest repository location
.TP
\fB\-b\fR REVISION, \fB\-\-manifest\-branch\fR=\fI\,REVISION\/\fR
manifest branch or revision (use HEAD for default)
.TP
\fB\-m\fR NAME.xml, \fB\-\-manifest\-name\fR=\fI\,NAME\/\fR.xml
initial manifest file
.TP
\fB\-\-standalone\-manifest\fR
download the manifest as a static file rather then
create a git checkout of the manifest repo
.TP
\fB\-g\fR GROUP, \fB\-\-groups\fR=\fI\,GROUP\/\fR
restrict manifest projects to ones with specified
group(s) [default|all|G1,G2,G3|G4,\-G5,\-G6]
.TP
\fB\-p\fR PLATFORM, \fB\-\-platform\fR=\fI\,PLATFORM\/\fR
restrict manifest projects to ones with a specified
platform group [auto|all|none|linux|darwin|...]
.TP
\fB\-\-submodules\fR
sync any submodules associated with the manifest repo
.SS Manifest (only) checkout options:
.TP
\fB\-c\fR, \fB\-\-current\-branch\fR
fetch only current manifest branch from server
.TP
\fB\-\-no\-current\-branch\fR
fetch all manifest branches from server
.TP
\fB\-\-tags\fR
fetch tags in the manifest
.TP
\fB\-\-no\-tags\fR
don't fetch tags in the manifest
.SS Checkout modes:
.TP
\fB\-\-mirror\fR
create a replica of the remote repositories rather
than a client working directory
.TP
\fB\-\-archive\fR
checkout an archive instead of a git repository for
each project. See git archive.
.TP
\fB\-\-worktree\fR
use git\-worktree to manage projects
.SS Project checkout optimizations:
.TP
\fB\-\-reference\fR=\fI\,DIR\/\fR
location of mirror directory
.TP
\fB\-\-dissociate\fR
dissociate from reference mirrors after clone
.TP
\fB\-\-depth\fR=\fI\,DEPTH\/\fR
create a shallow clone with given depth; see git clone
.TP
\fB\-\-partial\-clone\fR
perform partial clone (https://gitscm.com/docs/gitrepositorylayout#_code_partialclone_code)
.TP
\fB\-\-no\-partial\-clone\fR
disable use of partial clone (https://gitscm.com/docs/gitrepositorylayout#_code_partialclone_code)
.TP
\fB\-\-partial\-clone\-exclude\fR=\fI\,PARTIAL_CLONE_EXCLUDE\/\fR
exclude the specified projects (a comma\-delimited
project names) from partial clone (https://gitscm.com/docs/gitrepositorylayout#_code_partialclone_code)
.TP
\fB\-\-clone\-filter\fR=\fI\,CLONE_FILTER\/\fR
filter for use with \fB\-\-partial\-clone\fR [default:
blob:none]
.TP
\fB\-\-use\-superproject\fR
use the manifest superproject to sync projects
.TP
\fB\-\-no\-use\-superproject\fR
disable use of manifest superprojects
.TP
\fB\-\-clone\-bundle\fR
enable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
not \fB\-\-partial\-clone\fR)
.TP
\fB\-\-no\-clone\-bundle\fR
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
\fB\-\-partial\-clone\fR)
.SS repo Version options:
.TP
\fB\-\-repo\-url\fR=\fI\,URL\/\fR
repo repository location ($REPO_URL)
.TP
\fB\-\-repo\-rev\fR=\fI\,REV\/\fR
repo branch or revision ($REPO_REV)
.TP
\fB\-\-no\-repo\-verify\fR
do not verify repo source code
.SS Other options:
.TP
\fB\-\-config\-name\fR
Always prompt for name/e\-mail
.PP
Run `repo help init` to view the detailed manual.
.SH DETAILS
.PP
The 'repo init' command is run once to install and initialize repo. The latest
repo source code and manifest collection is downloaded from the server and is
installed in the .repo/ directory in the current working directory.
.PP
When creating a new checkout, the manifest URL is the only required setting. It
may be specified using the \fB\-\-manifest\-url\fR option, or as the first optional
argument.
.PP
The optional \fB\-b\fR argument can be used to select the manifest branch to checkout
and use. If no branch is specified, the remote's default branch is used. This is
equivalent to using \fB\-b\fR HEAD.
.PP
The optional \fB\-m\fR argument can be used to specify an alternate manifest to be
used. If no manifest is specified, the manifest default.xml will be used.
.PP
If the \fB\-\-standalone\-manifest\fR argument is set, the manifest will be downloaded
directly from the specified \fB\-\-manifest\-url\fR as a static file (rather than setting
up a manifest git checkout). With \fB\-\-standalone\-manifest\fR, the manifest will be
fully static and will not be re\-downloaded during subsesquent `repo init` and
`repo sync` calls.
.PP
The \fB\-\-reference\fR option can be used to point to a directory that has the content
of a \fB\-\-mirror\fR sync. This will make the working directory use as much data as
possible from the local reference directory when fetching from the server. This
will make the sync go a lot faster by reducing data traffic on the network.
.PP
The \fB\-\-dissociate\fR option can be used to borrow the objects from the directory
specified with the \fB\-\-reference\fR option only to reduce network transfer, and stop
borrowing from them after a first clone is made by making necessary local copies
of borrowed objects.
.PP
The \fB\-\-no\-clone\-bundle\fR option disables any attempt to use \fI\,$URL/clone.bundle\/\fP to
bootstrap a new Git repository from a resumeable bundle file on a content
delivery network. This may be necessary if there are problems with the local
Python HTTP client or proxy configuration, but the Git binary works.
.PP
Switching Manifest Branches
.PP
To switch to another manifest branch, `repo init \fB\-b\fR otherbranch` may be used in
an existing client. However, as this only updates the manifest, a subsequent
`repo sync` (or `repo sync \fB\-d\fR`) is necessary to update the working directory
files.

61
man/repo-list.1 Normal file
View File

@ -0,0 +1,61 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo list" "Repo Manual"
.SH NAME
repo \- repo list - manual page for repo list
.SH SYNOPSIS
.B repo
\fI\,list \/\fR[\fI\,-f\/\fR] [\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
List projects and their associated directories
.PP
repo list [\-f] \fB\-r\fR str1 [str2]...
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-r\fR, \fB\-\-regex\fR
filter the project list based on regex or wildcard
matching of strings
.TP
\fB\-g\fR GROUPS, \fB\-\-groups\fR=\fI\,GROUPS\/\fR
filter the project list based on the groups the
project is in
.TP
\fB\-a\fR, \fB\-\-all\fR
show projects regardless of checkout state
.TP
\fB\-n\fR, \fB\-\-name\-only\fR
display only the name of the repository
.TP
\fB\-p\fR, \fB\-\-path\-only\fR
display only the path of the repository
.TP
\fB\-f\fR, \fB\-\-fullpath\fR
display the full work tree path instead of the
relative path
.TP
\fB\-\-relative\-to\fR=\fI\,PATH\/\fR
display paths relative to this one (default: top of
repo client checkout)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help list` to view the detailed manual.
.SH DETAILS
.PP
List all projects; pass '.' to list the project for the cwd.
.PP
By default, only projects that currently exist in the checkout are shown. If you
want to list all projects (using the specified filter settings), use the \fB\-\-all\fR
option. If you want to show all projects regardless of the manifest groups, then
also pass \fB\-\-groups\fR all.
.PP
This is similar to running: repo forall \fB\-c\fR 'echo "$REPO_PATH : $REPO_PROJECT"'.

548
man/repo-manifest.1 Normal file
View File

@ -0,0 +1,548 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo manifest" "Repo Manual"
.SH NAME
repo \- repo manifest - manual page for repo manifest
.SH SYNOPSIS
.B repo
\fI\,manifest \/\fR[\fI\,-o {-|NAME.xml}\/\fR] [\fI\,-m MANIFEST.xml\/\fR] [\fI\,-r\/\fR]
.SH DESCRIPTION
Summary
.PP
Manifest inspection utility
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-r\fR, \fB\-\-revision\-as\-HEAD\fR
save revisions as current HEAD
.TP
\fB\-m\fR NAME.xml, \fB\-\-manifest\-name\fR=\fI\,NAME\/\fR.xml
temporary manifest to use for this sync
.TP
\fB\-\-suppress\-upstream\-revision\fR
if in \fB\-r\fR mode, do not write the upstream field (only
of use if the branch names for a sha1 manifest are
sensitive)
.TP
\fB\-\-suppress\-dest\-branch\fR
if in \fB\-r\fR mode, do not write the dest\-branch field
(only of use if the branch names for a sha1 manifest
are sensitive)
.TP
\fB\-\-json\fR
output manifest in JSON format (experimental)
.TP
\fB\-\-pretty\fR
format output for humans to read
.TP
\fB\-\-no\-local\-manifests\fR
ignore local manifests
.TP
\fB\-o\fR \-|NAME.xml, \fB\-\-output\-file\fR=\fI\,\-\/\fR|NAME.xml
file to save the manifest to
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help manifest` to view the detailed manual.
.SH DETAILS
.PP
With the \fB\-o\fR option, exports the current manifest for inspection. The manifest
and (if present) local_manifests/ are combined together to produce a single
manifest file. This file can be stored in a Git repository for use during future
\&'repo init' invocations.
.PP
The \fB\-r\fR option can be used to generate a manifest file with project revisions set
to the current commit hash. These are known as "revision locked manifests", as
they don't follow a particular branch. In this case, the 'upstream' attribute is
set to the ref we were on when the manifest was generated. The 'dest\-branch'
attribute is set to indicate the remote ref to push changes to via 'repo
upload'.
.PP
repo Manifest Format
.PP
A repo manifest describes the structure of a repo client; that is the
directories that are visible and where they should be obtained from with git.
.PP
The basic structure of a manifest is a bare Git repository holding a single
`default.xml` XML file in the top level directory.
.PP
Manifests are inherently version controlled, since they are kept within a Git
repository. Updates to manifests are automatically obtained by clients during
`repo sync`.
.PP
[TOC]
.PP
XML File Format
.PP
A manifest XML file (e.g. `default.xml`) roughly conforms to the following DTD:
.PP
```xml <!DOCTYPE manifest [
.TP
<!ELEMENT manifest (notice?,
remote*,
default?,
manifest\-server?,
remove\-project*,
project*,
extend\-project*,
repo\-hooks?,
superproject?,
contactinfo?,
include*)>
.IP
<!ELEMENT notice (#PCDATA)>
.IP
<!ELEMENT remote (annotation*)>
<!ATTLIST remote name ID #REQUIRED>
<!ATTLIST remote alias CDATA #IMPLIED>
<!ATTLIST remote fetch CDATA #REQUIRED>
<!ATTLIST remote pushurl CDATA #IMPLIED>
<!ATTLIST remote review CDATA #IMPLIED>
<!ATTLIST remote revision CDATA #IMPLIED>
.IP
<!ELEMENT default EMPTY>
<!ATTLIST default remote IDREF #IMPLIED>
<!ATTLIST default revision CDATA #IMPLIED>
<!ATTLIST default dest\-branch CDATA #IMPLIED>
<!ATTLIST default upstream CDATA #IMPLIED>
<!ATTLIST default sync\-j CDATA #IMPLIED>
<!ATTLIST default sync\-c CDATA #IMPLIED>
<!ATTLIST default sync\-s CDATA #IMPLIED>
<!ATTLIST default sync\-tags CDATA #IMPLIED>
.IP
<!ELEMENT manifest\-server EMPTY>
<!ATTLIST manifest\-server url CDATA #REQUIRED>
.TP
<!ELEMENT project (annotation*,
project*,
copyfile*,
linkfile*)>
.TP
<!ATTLIST project name
CDATA #REQUIRED>
.TP
<!ATTLIST project path
CDATA #IMPLIED>
.TP
<!ATTLIST project remote
IDREF #IMPLIED>
.TP
<!ATTLIST project revision
CDATA #IMPLIED>
.IP
<!ATTLIST project dest\-branch CDATA #IMPLIED>
<!ATTLIST project groups CDATA #IMPLIED>
<!ATTLIST project sync\-c CDATA #IMPLIED>
<!ATTLIST project sync\-s CDATA #IMPLIED>
<!ATTLIST project sync\-tags CDATA #IMPLIED>
<!ATTLIST project upstream CDATA #IMPLIED>
<!ATTLIST project clone\-depth CDATA #IMPLIED>
<!ATTLIST project force\-path CDATA #IMPLIED>
.IP
<!ELEMENT annotation EMPTY>
<!ATTLIST annotation name CDATA #REQUIRED>
<!ATTLIST annotation value CDATA #REQUIRED>
<!ATTLIST annotation keep CDATA "true">
.IP
<!ELEMENT copyfile EMPTY>
<!ATTLIST copyfile src CDATA #REQUIRED>
<!ATTLIST copyfile dest CDATA #REQUIRED>
.IP
<!ELEMENT linkfile EMPTY>
<!ATTLIST linkfile src CDATA #REQUIRED>
<!ATTLIST linkfile dest CDATA #REQUIRED>
.IP
<!ELEMENT extend\-project EMPTY>
<!ATTLIST extend\-project name CDATA #REQUIRED>
<!ATTLIST extend\-project path CDATA #IMPLIED>
<!ATTLIST extend\-project groups CDATA #IMPLIED>
<!ATTLIST extend\-project revision CDATA #IMPLIED>
<!ATTLIST extend\-project remote CDATA #IMPLIED>
.IP
<!ELEMENT remove\-project EMPTY>
<!ATTLIST remove\-project name CDATA #REQUIRED>
<!ATTLIST remove\-project optional CDATA #IMPLIED>
.IP
<!ELEMENT repo\-hooks EMPTY>
<!ATTLIST repo\-hooks in\-project CDATA #REQUIRED>
<!ATTLIST repo\-hooks enabled\-list CDATA #REQUIRED>
.IP
<!ELEMENT superproject EMPTY>
<!ATTLIST superproject name CDATA #REQUIRED>
<!ATTLIST superproject remote IDREF #IMPLIED>
.IP
<!ELEMENT contactinfo EMPTY>
<!ATTLIST contactinfo bugurl CDATA #REQUIRED>
.IP
<!ELEMENT include EMPTY>
<!ATTLIST include name CDATA #REQUIRED>
<!ATTLIST include groups CDATA #IMPLIED>
.PP
]>
```
.PP
For compatibility purposes across repo releases, all unknown elements are
silently ignored. However, repo reserves all possible names for itself for
future use. If you want to use custom elements, the `x\-*` namespace is reserved
for that purpose, and repo guarantees to never allocate any corresponding names.
.PP
A description of the elements and their attributes follows.
.PP
Element manifest
.PP
The root element of the file.
.PP
Element notice
.PP
Arbitrary text that is displayed to users whenever `repo sync` finishes. The
content is simply passed through as it exists in the manifest.
.PP
Element remote
.PP
One or more remote elements may be specified. Each remote element specifies a
Git URL shared by one or more projects and (optionally) the Gerrit review server
those projects upload changes through.
.PP
Attribute `name`: A short name unique to this manifest file. The name specified
here is used as the remote name in each project's .git/config, and is therefore
automatically available to commands like `git fetch`, `git remote`, `git pull`
and `git push`.
.PP
Attribute `alias`: The alias, if specified, is used to override `name` to be set
as the remote name in each project's .git/config. Its value can be duplicated
while attribute `name` has to be unique in the manifest file. This helps each
project to be able to have same remote name which actually points to different
remote url.
.PP
Attribute `fetch`: The Git URL prefix for all projects which use this remote.
Each project's name is appended to this prefix to form the actual URL used to
clone the project.
.PP
Attribute `pushurl`: The Git "push" URL prefix for all projects which use this
remote. Each project's name is appended to this prefix to form the actual URL
used to "git push" the project. This attribute is optional; if not specified
then "git push" will use the same URL as the `fetch` attribute.
.PP
Attribute `review`: Hostname of the Gerrit server where reviews are uploaded to
by `repo upload`. This attribute is optional; if not specified then `repo
upload` will not function.
.PP
Attribute `revision`: Name of a Git branch (e.g. `main` or `refs/heads/main`).
Remotes with their own revision will override the default revision.
.PP
Element default
.PP
At most one default element may be specified. Its remote and revision attributes
are used when a project element does not specify its own remote or revision
attribute.
.PP
Attribute `remote`: Name of a previously defined remote element. Project
elements lacking a remote attribute of their own will use this remote.
.PP
Attribute `revision`: Name of a Git branch (e.g. `main` or `refs/heads/main`).
Project elements lacking their own revision attribute will use this revision.
.PP
Attribute `dest\-branch`: Name of a Git branch (e.g. `main`). Project elements
not setting their own `dest\-branch` will inherit this value. If this value is
not set, projects will use `revision` by default instead.
.PP
Attribute `upstream`: Name of the Git ref in which a sha1 can be found. Used
when syncing a revision locked manifest in \fB\-c\fR mode to avoid having to sync the
entire ref space. Project elements not setting their own `upstream` will inherit
this value.
.PP
Attribute `sync\-j`: Number of parallel jobs to use when synching.
.PP
Attribute `sync\-c`: Set to true to only sync the given Git branch (specified in
the `revision` attribute) rather than the whole ref space. Project elements
lacking a sync\-c element of their own will use this value.
.PP
Attribute `sync\-s`: Set to true to also sync sub\-projects.
.PP
Attribute `sync\-tags`: Set to false to only sync the given Git branch (specified
in the `revision` attribute) rather than the other ref tags.
.PP
Element manifest\-server
.PP
At most one manifest\-server may be specified. The url attribute is used to
specify the URL of a manifest server, which is an XML RPC service.
.PP
The manifest server should implement the following RPC methods:
.IP
GetApprovedManifest(branch, target)
.PP
Return a manifest in which each project is pegged to a known good revision for
the current branch and target. This is used by repo sync when the \fB\-\-smart\-sync\fR
option is given.
.PP
The target to use is defined by environment variables TARGET_PRODUCT and
TARGET_BUILD_VARIANT. These variables are used to create a string of the form
$TARGET_PRODUCT\-$TARGET_BUILD_VARIANT, e.g. passion\-userdebug. If one of those
variables or both are not present, the program will call GetApprovedManifest
without the target parameter and the manifest server should choose a reasonable
default target.
.IP
GetManifest(tag)
.PP
Return a manifest in which each project is pegged to the revision at the
specified tag. This is used by repo sync when the \fB\-\-smart\-tag\fR option is given.
.PP
Element project
.PP
One or more project elements may be specified. Each element describes a single
Git repository to be cloned into the repo client workspace. You may specify
Git\-submodules by creating a nested project. Git\-submodules will be
automatically recognized and inherit their parent's attributes, but those may be
overridden by an explicitly specified project element.
.PP
Attribute `name`: A unique name for this project. The project's name is appended
onto its remote's fetch URL to generate the actual URL to configure the Git
remote with. The URL gets formed as:
.IP
${remote_fetch}/${project_name}.git
.PP
where ${remote_fetch} is the remote's fetch attribute and ${project_name} is the
project's name attribute. The suffix ".git" is always appended as repo assumes
the upstream is a forest of bare Git repositories. If the project has a parent
element, its name will be prefixed by the parent's.
.PP
The project name must match the name Gerrit knows, if Gerrit is being used for
code reviews.
.PP
"name" must not be empty, and may not be an absolute path or use "." or ".."
path components. It is always interpreted relative to the remote's fetch
settings, so if a different base path is needed, declare a different remote with
the new settings needed. These restrictions are not enforced for [Local
Manifests].
.PP
Attribute `path`: An optional path relative to the top directory of the repo
client where the Git working directory for this project should be placed. If not
supplied the project "name" is used. If the project has a parent element, its
path will be prefixed by the parent's.
.PP
"path" may not be an absolute path or use "." or ".." path components. These
restrictions are not enforced for [Local Manifests].
.PP
If you want to place files into the root of the checkout (e.g. a README or
Makefile or another build script), use the [copyfile] or [linkfile] elements
instead.
.PP
Attribute `remote`: Name of a previously defined remote element. If not supplied
the remote given by the default element is used.
.PP
Attribute `revision`: Name of the Git branch the manifest wants to track for
this project. Names can be relative to refs/heads (e.g. just "main") or absolute
(e.g. "refs/heads/main"). Tags and/or explicit SHA\-1s should work in theory, but
have not been extensively tested. If not supplied the revision given by the
remote element is used if applicable, else the default element is used.
.PP
Attribute `dest\-branch`: Name of a Git branch (e.g. `main`). When using `repo
upload`, changes will be submitted for code review on this branch. If
unspecified both here and in the default element, `revision` is used instead.
.PP
Attribute `groups`: List of groups to which this project belongs, whitespace or
comma separated. All projects belong to the group "all", and each project
automatically belongs to a group of its name:`name` and path:`path`. E.g. for
`<project name="monkeys" path="barrel\-of"/>`, that project definition is
implicitly in the following manifest groups: default, name:monkeys, and
path:barrel\-of. If you place a project in the group "notdefault", it will not be
automatically downloaded by repo. If the project has a parent element, the
`name` and `path` here are the prefixed ones.
.PP
Attribute `sync\-c`: Set to true to only sync the given Git branch (specified in
the `revision` attribute) rather than the whole ref space.
.PP
Attribute `sync\-s`: Set to true to also sync sub\-projects.
.PP
Attribute `upstream`: Name of the Git ref in which a sha1 can be found. Used
when syncing a revision locked manifest in \fB\-c\fR mode to avoid having to sync the
entire ref space.
.PP
Attribute `clone\-depth`: Set the depth to use when fetching this project. If
specified, this value will override any value given to repo init with the
\fB\-\-depth\fR option on the command line.
.PP
Attribute `force\-path`: Set to true to force this project to create the local
mirror repository according to its `path` attribute (if supplied) rather than
the `name` attribute. This attribute only applies to the local mirrors syncing,
it will be ignored when syncing the projects in a client working directory.
.PP
Element extend\-project
.PP
Modify the attributes of the named project.
.PP
This element is mostly useful in a local manifest file, to modify the attributes
of an existing project without completely replacing the existing project
definition. This makes the local manifest more robust against changes to the
original manifest.
.PP
Attribute `path`: If specified, limit the change to projects checked out at the
specified path, rather than all projects with the given name.
.PP
Attribute `groups`: List of additional groups to which this project belongs.
Same syntax as the corresponding element of `project`.
.PP
Attribute `revision`: If specified, overrides the revision of the original
project. Same syntax as the corresponding element of `project`.
.PP
Attribute `remote`: If specified, overrides the remote of the original project.
Same syntax as the corresponding element of `project`.
.PP
Element annotation
.PP
Zero or more annotation elements may be specified as children of a project or
remote element. Each element describes a name\-value pair. For projects, this
name\-value pair will be exported into each project's environment during a
\&'forall' command, prefixed with `REPO__`. In addition, there is an optional
attribute "keep" which accepts the case insensitive values "true" (default) or
"false". This attribute determines whether or not the annotation will be kept
when exported with the manifest subcommand.
.PP
Element copyfile
.PP
Zero or more copyfile elements may be specified as children of a project
element. Each element describes a src\-dest pair of files; the "src" file will be
copied to the "dest" place during `repo sync` command.
.PP
"src" is project relative, "dest" is relative to the top of the tree. Copying
from paths outside of the project or to paths outside of the repo client is not
allowed.
.PP
"src" and "dest" must be files. Directories or symlinks are not allowed.
Intermediate paths must not be symlinks either.
.PP
Parent directories of "dest" will be automatically created if missing.
.PP
Element linkfile
.PP
It's just like copyfile and runs at the same time as copyfile but instead of
copying it creates a symlink.
.PP
The symlink is created at "dest" (relative to the top of the tree) and points to
the path specified by "src" which is a path in the project.
.PP
Parent directories of "dest" will be automatically created if missing.
.PP
The symlink target may be a file or directory, but it may not point outside of
the repo client.
.PP
Element remove\-project
.PP
Deletes the named project from the internal manifest table, possibly allowing a
subsequent project element in the same manifest file to replace the project with
a different source.
.PP
This element is mostly useful in a local manifest file, where the user can
remove a project, and possibly replace it with their own definition.
.PP
Attribute `optional`: Set to true to ignore remove\-project elements with no
matching `project` element.
.PP
Element repo\-hooks
.PP
NB: See the [practical documentation](./repo\-hooks.md) for using repo hooks.
.PP
Only one repo\-hooks element may be specified at a time. Attempting to redefine
it will fail to parse.
.PP
Attribute `in\-project`: The project where the hooks are defined. The value must
match the `name` attribute (**not** the `path` attribute) of a previously
defined `project` element.
.PP
Attribute `enabled\-list`: List of hooks to use, whitespace or comma separated.
.PP
Element superproject
.PP
*** *Note*: This is currently a WIP. ***
.PP
NB: See the [git superprojects documentation](
https://en.wikibooks.org/wiki/Git/Submodules_and_Superprojects) for background
information.
.PP
This element is used to specify the URL of the superproject. It has "name" and
"remote" as atrributes. Only "name" is required while the others have reasonable
defaults. At most one superproject may be specified. Attempting to redefine it
will fail to parse.
.PP
Attribute `name`: A unique name for the superproject. This attribute has the
same meaning as project's name attribute. See the [element
project](#element\-project) for more information.
.PP
Attribute `remote`: Name of a previously defined remote element. If not supplied
the remote given by the default element is used.
.PP
Element contactinfo
.PP
*** *Note*: This is currently a WIP. ***
.PP
This element is used to let manifest authors self\-register contact info. It has
"bugurl" as a required atrribute. This element can be repeated, and any later
entries will clobber earlier ones. This would allow manifest authors who extend
manifests to specify their own contact info.
.PP
Attribute `bugurl`: The URL to file a bug against the manifest owner.
.PP
Element include
.PP
This element provides the capability of including another manifest file into the
originating manifest. Normal rules apply for the target manifest to include \- it
must be a usable manifest on its own.
.PP
Attribute `name`: the manifest to include, specified relative to the manifest
repository's root.
.PP
"name" may not be an absolute path or use "." or ".." path components. These
restrictions are not enforced for [Local Manifests].
.PP
Attribute `groups`: List of additional groups to which all projects in the
included manifest belong. This appends and recurses, meaning all projects in
sub\-manifests carry all parent include groups. Same syntax as the corresponding
element of `project`.
.PP
Local Manifests
.PP
Additional remotes and projects may be added through local manifest files stored
in `$TOP_DIR/.repo/local_manifests/*.xml`.
.PP
For example:
.IP
\f(CW$ ls .repo/local_manifests\fR
.IP
local_manifest.xml
another_local_manifest.xml
.IP
\f(CW$ cat .repo/local_manifests/local_manifest.xml\fR
.IP
<?xml version="1.0" encoding="UTF\-8"?>
<manifest>
.IP
<project path="manifest"
.IP
name="tools/manifest" />
.IP
<project path="platform\-manifest"
.IP
name="platform/manifest" />
.IP
</manifest>
.PP
Users may add projects to the local manifest(s) prior to a `repo sync`
invocation, instructing repo to automatically download and manage these extra
projects.
.PP
Manifest files stored in `$TOP_DIR/.repo/local_manifests/*.xml` will be loaded
in alphabetical order.
.PP
Projects from local manifest files are added into local::<local manifest
filename> group.
.PP
The legacy `$TOP_DIR/.repo/local_manifest.xml` path is no longer supported.
.SS [copyfile]: #Element\-copyfile [linkfile]: #Element\-linkfile [Local Manifests]:
.PP
#local\-manifests

39
man/repo-overview.1 Normal file
View File

@ -0,0 +1,39 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo overview" "Repo Manual"
.SH NAME
repo \- repo overview - manual page for repo overview
.SH SYNOPSIS
.B repo
\fI\,overview \/\fR[\fI\,--current-branch\/\fR] [\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Display overview of unmerged project branches
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-c\fR, \fB\-\-current\-branch\fR
consider only checked out branches
.TP
\fB\-\-no\-current\-branch\fR
consider all local branches
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help overview` to view the detailed manual.
.SH DETAILS
.PP
The 'repo overview' command is used to display an overview of the projects
branches, and list any local commits that have not yet been merged into the
project.
.PP
The \fB\-c\fR/\-\-current\-branch option can be used to restrict the output to only
branches currently checked out in each project. By default, all branches are
displayed.

28
man/repo-prune.1 Normal file
View File

@ -0,0 +1,28 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo prune" "Repo Manual"
.SH NAME
repo \- repo prune - manual page for repo prune
.SH SYNOPSIS
.B repo
\fI\,prune \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Prune (delete) already merged topics
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help prune` to view the detailed manual.

55
man/repo-rebase.1 Normal file
View File

@ -0,0 +1,55 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo rebase" "Repo Manual"
.SH NAME
repo \- repo rebase - manual page for repo rebase
.SH SYNOPSIS
.B repo
\fI\,rebase {\/\fR[\fI\,<project>\/\fR...] \fI\,| -i <project>\/\fR...\fI\,}\/\fR
.SH DESCRIPTION
Summary
.PP
Rebase local branches on upstream branch
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-\-fail\-fast\fR
stop rebasing after first error is hit
.TP
\fB\-f\fR, \fB\-\-force\-rebase\fR
pass \fB\-\-force\-rebase\fR to git rebase
.TP
\fB\-\-no\-ff\fR
pass \fB\-\-no\-ff\fR to git rebase
.TP
\fB\-\-autosquash\fR
pass \fB\-\-autosquash\fR to git rebase
.TP
\fB\-\-whitespace\fR=\fI\,WS\/\fR
pass \fB\-\-whitespace\fR to git rebase
.TP
\fB\-\-auto\-stash\fR
stash local modifications before starting
.TP
\fB\-m\fR, \fB\-\-onto\-manifest\fR
rebase onto the manifest version instead of upstream
HEAD (this helps to make sure the local tree stays
consistent if you previously synced to a manifest)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.TP
\fB\-i\fR, \fB\-\-interactive\fR
interactive rebase (single project only)
.PP
Run `repo help rebase` to view the detailed manual.
.SH DETAILS
.PP
\&'repo rebase' uses git rebase to move local changes in the current topic branch
to the HEAD of the upstream history, useful when you have made commits in a
topic branch but need to incorporate new upstream changes "underneath" them.

35
man/repo-selfupdate.1 Normal file
View File

@ -0,0 +1,35 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo selfupdate" "Repo Manual"
.SH NAME
repo \- repo selfupdate - manual page for repo selfupdate
.SH SYNOPSIS
.B repo
\fI\,selfupdate\/\fR
.SH DESCRIPTION
Summary
.PP
Update repo to the latest version
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS repo Version options:
.TP
\fB\-\-no\-repo\-verify\fR
do not verify repo source code
.PP
Run `repo help selfupdate` to view the detailed manual.
.SH DETAILS
.PP
The 'repo selfupdate' command upgrades repo to the latest version, if a newer
version is available.
.PP
Normally this is done automatically by 'repo sync' and does not need to be
performed by an end\-user.

118
man/repo-smartsync.1 Normal file
View File

@ -0,0 +1,118 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo smartsync" "Repo Manual"
.SH NAME
repo \- repo smartsync - manual page for repo smartsync
.SH SYNOPSIS
.B repo
\fI\,smartsync \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Update working tree to the latest known good revision
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-\-jobs\-network\fR=\fI\,JOBS\/\fR
number of network jobs to run in parallel (defaults to
\fB\-\-jobs\fR)
.TP
\fB\-\-jobs\-checkout\fR=\fI\,JOBS\/\fR
number of local checkout jobs to run in parallel
(defaults to \fB\-\-jobs\fR)
.TP
\fB\-f\fR, \fB\-\-force\-broken\fR
obsolete option (to be deleted in the future)
.TP
\fB\-\-fail\-fast\fR
stop syncing after first error is hit
.TP
\fB\-\-force\-sync\fR
overwrite an existing git directory if it needs to
point to a different object directory. WARNING: this
may cause loss of data
.TP
\fB\-\-force\-remove\-dirty\fR
force remove projects with uncommitted modifications
if projects no longer exist in the manifest. WARNING:
this may cause loss of data
.TP
\fB\-l\fR, \fB\-\-local\-only\fR
only update working tree, don't fetch
.TP
\fB\-\-no\-manifest\-update\fR, \fB\-\-nmu\fR
use the existing manifest checkout as\-is. (do not
update to the latest revision)
.TP
\fB\-n\fR, \fB\-\-network\-only\fR
fetch only, don't update working tree
.TP
\fB\-d\fR, \fB\-\-detach\fR
detach projects back to manifest revision
.TP
\fB\-c\fR, \fB\-\-current\-branch\fR
fetch only current branch from server
.TP
\fB\-\-no\-current\-branch\fR
fetch all branches from server
.TP
\fB\-m\fR NAME.xml, \fB\-\-manifest\-name\fR=\fI\,NAME\/\fR.xml
temporary manifest to use for this sync
.TP
\fB\-\-clone\-bundle\fR
enable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS
.TP
\fB\-\-no\-clone\-bundle\fR
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS
.TP
\fB\-u\fR MANIFEST_SERVER_USERNAME, \fB\-\-manifest\-server\-username\fR=\fI\,MANIFEST_SERVER_USERNAME\/\fR
username to authenticate with the manifest server
.TP
\fB\-p\fR MANIFEST_SERVER_PASSWORD, \fB\-\-manifest\-server\-password\fR=\fI\,MANIFEST_SERVER_PASSWORD\/\fR
password to authenticate with the manifest server
.TP
\fB\-\-fetch\-submodules\fR
fetch submodules from server
.TP
\fB\-\-use\-superproject\fR
use the manifest superproject to sync projects
.TP
\fB\-\-no\-use\-superproject\fR
disable use of manifest superprojects
.TP
\fB\-\-tags\fR
fetch tags
.TP
\fB\-\-no\-tags\fR
don't fetch tags
.TP
\fB\-\-optimized\-fetch\fR
only fetch projects fixed to sha1 if revision does not
exist locally
.TP
\fB\-\-retry\-fetches\fR=\fI\,RETRY_FETCHES\/\fR
number of times to retry fetches on transient errors
.TP
\fB\-\-prune\fR
delete refs that no longer exist on the remote
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS repo Version options:
.TP
\fB\-\-no\-repo\-verify\fR
do not verify repo source code
.PP
Run `repo help smartsync` to view the detailed manual.
.SH DETAILS
.PP
The 'repo smartsync' command is a shortcut for sync \fB\-s\fR.

30
man/repo-stage.1 Normal file
View File

@ -0,0 +1,30 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo stage" "Repo Manual"
.SH NAME
repo \- repo stage - manual page for repo stage
.SH SYNOPSIS
.B repo
\fI\,stage -i \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Stage file(s) for commit
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.TP
\fB\-i\fR, \fB\-\-interactive\fR
use interactive staging
.PP
Run `repo help stage` to view the detailed manual.
.SH DETAILS
.PP
The 'repo stage' command stages files to prepare the next commit.

41
man/repo-start.1 Normal file
View File

@ -0,0 +1,41 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo start" "Repo Manual"
.SH NAME
repo \- repo start - manual page for repo start
.SH SYNOPSIS
.B repo
\fI\,start <newbranchname> \/\fR[\fI\,--all | <project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Start a new branch for development
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-\-all\fR
begin branch in all projects
.TP
\fB\-r\fR REVISION, \fB\-\-rev\fR=\fI\,REVISION\/\fR, \fB\-\-revision\fR=\fI\,REVISION\/\fR
point branch at this revision instead of upstream
.TP
\fB\-\-head\fR, \fB\-\-HEAD\fR
abbreviation for \fB\-\-rev\fR HEAD
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help start` to view the detailed manual.
.SH DETAILS
.PP
\&'repo start' begins a new branch of development, starting from the revision
specified in the manifest.

98
man/repo-status.1 Normal file
View File

@ -0,0 +1,98 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo status" "Repo Manual"
.SH NAME
repo \- repo status - manual page for repo status
.SH SYNOPSIS
.B repo
\fI\,status \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Show the working tree status
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-o\fR, \fB\-\-orphans\fR
include objects in working directory outside of repo
projects
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help status` to view the detailed manual.
.SH DETAILS
.PP
\&'repo status' compares the working tree to the staging area (aka index), and the
most recent commit on this branch (HEAD), in each project specified. A summary
is displayed, one line per file where there is a difference between these three
states.
.PP
The \fB\-j\fR/\-\-jobs option can be used to run multiple status queries in parallel.
.PP
The \fB\-o\fR/\-\-orphans option can be used to show objects that are in the working
directory, but not associated with a repo project. This includes unmanaged
top\-level files and directories, but also includes deeper items. For example, if
dir/subdir/proj1 and dir/subdir/proj2 are repo projects, dir/subdir/proj3 will
be shown if it is not known to repo.
.PP
Status Display
.PP
The status display is organized into three columns of information, for example
if the file 'subcmds/status.py' is modified in the project 'repo' on branch
\&'devwork':
.TP
project repo/
branch devwork
.TP
\fB\-m\fR
subcmds/status.py
.PP
The first column explains how the staging area (index) differs from the last
commit (HEAD). Its values are always displayed in upper case and have the
following meanings:
.TP
\-:
no difference
.TP
A:
added (not in HEAD, in index )
.TP
M:
modified ( in HEAD, in index, different content )
.TP
D:
deleted ( in HEAD, not in index )
.TP
R:
renamed (not in HEAD, in index, path changed )
.TP
C:
copied (not in HEAD, in index, copied from another)
.TP
T:
mode changed ( in HEAD, in index, same content )
.TP
U:
unmerged; conflict resolution required
.PP
The second column explains how the working directory differs from the index. Its
values are always displayed in lower case and have the following meanings:
.TP
\-:
new / unknown (not in index, in work tree )
.TP
m:
modified ( in index, in work tree, modified )
.TP
d:
deleted ( in index, not in work tree )

209
man/repo-sync.1 Normal file
View File

@ -0,0 +1,209 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo sync" "Repo Manual"
.SH NAME
repo \- repo sync - manual page for repo sync
.SH SYNOPSIS
.B repo
\fI\,sync \/\fR[\fI\,<project>\/\fR...]
.SH DESCRIPTION
Summary
.PP
Update working tree to the latest revision
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-\-jobs\-network\fR=\fI\,JOBS\/\fR
number of network jobs to run in parallel (defaults to
\fB\-\-jobs\fR)
.TP
\fB\-\-jobs\-checkout\fR=\fI\,JOBS\/\fR
number of local checkout jobs to run in parallel
(defaults to \fB\-\-jobs\fR)
.TP
\fB\-f\fR, \fB\-\-force\-broken\fR
obsolete option (to be deleted in the future)
.TP
\fB\-\-fail\-fast\fR
stop syncing after first error is hit
.TP
\fB\-\-force\-sync\fR
overwrite an existing git directory if it needs to
point to a different object directory. WARNING: this
may cause loss of data
.TP
\fB\-\-force\-remove\-dirty\fR
force remove projects with uncommitted modifications
if projects no longer exist in the manifest. WARNING:
this may cause loss of data
.TP
\fB\-l\fR, \fB\-\-local\-only\fR
only update working tree, don't fetch
.TP
\fB\-\-no\-manifest\-update\fR, \fB\-\-nmu\fR
use the existing manifest checkout as\-is. (do not
update to the latest revision)
.TP
\fB\-n\fR, \fB\-\-network\-only\fR
fetch only, don't update working tree
.TP
\fB\-d\fR, \fB\-\-detach\fR
detach projects back to manifest revision
.TP
\fB\-c\fR, \fB\-\-current\-branch\fR
fetch only current branch from server
.TP
\fB\-\-no\-current\-branch\fR
fetch all branches from server
.TP
\fB\-m\fR NAME.xml, \fB\-\-manifest\-name\fR=\fI\,NAME\/\fR.xml
temporary manifest to use for this sync
.TP
\fB\-\-clone\-bundle\fR
enable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS
.TP
\fB\-\-no\-clone\-bundle\fR
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS
.TP
\fB\-u\fR MANIFEST_SERVER_USERNAME, \fB\-\-manifest\-server\-username\fR=\fI\,MANIFEST_SERVER_USERNAME\/\fR
username to authenticate with the manifest server
.TP
\fB\-p\fR MANIFEST_SERVER_PASSWORD, \fB\-\-manifest\-server\-password\fR=\fI\,MANIFEST_SERVER_PASSWORD\/\fR
password to authenticate with the manifest server
.TP
\fB\-\-fetch\-submodules\fR
fetch submodules from server
.TP
\fB\-\-use\-superproject\fR
use the manifest superproject to sync projects
.TP
\fB\-\-no\-use\-superproject\fR
disable use of manifest superprojects
.TP
\fB\-\-tags\fR
fetch tags
.TP
\fB\-\-no\-tags\fR
don't fetch tags
.TP
\fB\-\-optimized\-fetch\fR
only fetch projects fixed to sha1 if revision does not
exist locally
.TP
\fB\-\-retry\-fetches\fR=\fI\,RETRY_FETCHES\/\fR
number of times to retry fetches on transient errors
.TP
\fB\-\-prune\fR
delete refs that no longer exist on the remote
.TP
\fB\-s\fR, \fB\-\-smart\-sync\fR
smart sync using manifest from the latest known good
build
.TP
\fB\-t\fR SMART_TAG, \fB\-\-smart\-tag\fR=\fI\,SMART_TAG\/\fR
smart sync using manifest from a known tag
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS repo Version options:
.TP
\fB\-\-no\-repo\-verify\fR
do not verify repo source code
.PP
Run `repo help sync` to view the detailed manual.
.SH DETAILS
.PP
The 'repo sync' command synchronizes local project directories with the remote
repositories specified in the manifest. If a local project does not yet exist,
it will clone a new local directory from the remote repository and set up
tracking branches as specified in the manifest. If the local project already
exists, 'repo sync' will update the remote branches and rebase any new local
changes on top of the new remote changes.
.PP
\&'repo sync' will synchronize all projects listed at the command line. Projects
can be specified either by name, or by a relative or absolute path to the
project's local directory. If no projects are specified, 'repo sync' will
synchronize all projects listed in the manifest.
.PP
The \fB\-d\fR/\-\-detach option can be used to switch specified projects back to the
manifest revision. This option is especially helpful if the project is currently
on a topic branch, but the manifest revision is temporarily needed.
.PP
The \fB\-s\fR/\-\-smart\-sync option can be used to sync to a known good build as
specified by the manifest\-server element in the current manifest. The
\fB\-t\fR/\-\-smart\-tag option is similar and allows you to specify a custom tag/label.
.PP
The \fB\-u\fR/\-\-manifest\-server\-username and \fB\-p\fR/\-\-manifest\-server\-password options can
be used to specify a username and password to authenticate with the manifest
server when using the \fB\-s\fR or \fB\-t\fR option.
.PP
If \fB\-u\fR and \fB\-p\fR are not specified when using the \fB\-s\fR or \fB\-t\fR option, 'repo sync' will
attempt to read authentication credentials for the manifest server from the
user's .netrc file.
.PP
\&'repo sync' will not use authentication credentials from \fB\-u\fR/\-p or .netrc if the
manifest server specified in the manifest file already includes credentials.
.PP
By default, all projects will be synced. The \fB\-\-fail\-fast\fR option can be used to
halt syncing as soon as possible when the first project fails to sync.
.PP
The \fB\-\-force\-sync\fR option can be used to overwrite existing git directories if
they have previously been linked to a different object directory. WARNING: This
may cause data to be lost since refs may be removed when overwriting.
.PP
The \fB\-\-force\-remove\-dirty\fR option can be used to remove previously used projects
with uncommitted changes. WARNING: This may cause data to be lost since
uncommitted changes may be removed with projects that no longer exist in the
manifest.
.PP
The \fB\-\-no\-clone\-bundle\fR option disables any attempt to use \fI\,$URL/clone.bundle\/\fP to
bootstrap a new Git repository from a resumeable bundle file on a content
delivery network. This may be necessary if there are problems with the local
Python HTTP client or proxy configuration, but the Git binary works.
.PP
The \fB\-\-fetch\-submodules\fR option enables fetching Git submodules of a project from
server.
.PP
The \fB\-c\fR/\-\-current\-branch option can be used to only fetch objects that are on the
branch specified by a project's revision.
.PP
The \fB\-\-optimized\-fetch\fR option can be used to only fetch projects that are fixed
to a sha1 revision if the sha1 revision does not already exist locally.
.PP
The \fB\-\-prune\fR option can be used to remove any refs that no longer exist on the
remote.
.PP
SSH Connections
.PP
If at least one project remote URL uses an SSH connection (ssh://, git+ssh://,
or user@host:path syntax) repo will automatically enable the SSH ControlMaster
option when connecting to that host. This feature permits other projects in the
same 'repo sync' session to reuse the same SSH tunnel, saving connection setup
overheads.
.PP
To disable this behavior on UNIX platforms, set the GIT_SSH environment variable
to 'ssh'. For example:
.IP
export GIT_SSH=ssh
repo sync
.PP
Compatibility
.PP
This feature is automatically disabled on Windows, due to the lack of UNIX
domain socket support.
.PP
This feature is not compatible with url.insteadof rewrites in the user's
~/.gitconfig. 'repo sync' is currently not able to perform the rewrite early
enough to establish the ControlMaster tunnel.
.PP
If the remote SSH daemon is Gerrit Code Review, version 2.0.10 or later is
required to fix a server side protocol bug.

175
man/repo-upload.1 Normal file
View File

@ -0,0 +1,175 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo upload" "Repo Manual"
.SH NAME
repo \- repo upload - manual page for repo upload
.SH SYNOPSIS
.B repo
\fI\,upload \/\fR[\fI\,--re --cc\/\fR] [\fI\,<project>\/\fR]...
.SH DESCRIPTION
Summary
.PP
Upload changes for code review
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-j\fR JOBS, \fB\-\-jobs\fR=\fI\,JOBS\/\fR
number of jobs to run in parallel (default: based on
number of CPU cores)
.TP
\fB\-t\fR
send local branch name to Gerrit Code Review
.TP
\fB\-\-hashtag\fR=\fI\,HASHTAGS\/\fR, \fB\-\-ht\fR=\fI\,HASHTAGS\/\fR
add hashtags (comma delimited) to the review
.TP
\fB\-\-hashtag\-branch\fR, \fB\-\-htb\fR
add local branch name as a hashtag
.TP
\fB\-l\fR LABELS, \fB\-\-label\fR=\fI\,LABELS\/\fR
add a label when uploading
.TP
\fB\-\-re\fR=\fI\,REVIEWERS\/\fR, \fB\-\-reviewers\fR=\fI\,REVIEWERS\/\fR
request reviews from these people
.TP
\fB\-\-cc\fR=\fI\,CC\/\fR
also send email to these email addresses
.TP
\fB\-\-br\fR=\fI\,BRANCH\/\fR, \fB\-\-branch\fR=\fI\,BRANCH\/\fR
(local) branch to upload
.TP
\fB\-c\fR, \fB\-\-current\-branch\fR
upload current git branch
.TP
\fB\-\-no\-current\-branch\fR
upload all git branches
.TP
\fB\-\-ne\fR, \fB\-\-no\-emails\fR
do not send e\-mails on upload
.TP
\fB\-p\fR, \fB\-\-private\fR
upload as a private change (deprecated; use \fB\-\-wip\fR)
.TP
\fB\-w\fR, \fB\-\-wip\fR
upload as a work\-in\-progress change
.TP
\fB\-o\fR PUSH_OPTIONS, \fB\-\-push\-option\fR=\fI\,PUSH_OPTIONS\/\fR
additional push options to transmit
.TP
\fB\-D\fR BRANCH, \fB\-\-destination\fR=\fI\,BRANCH\/\fR, \fB\-\-dest\fR=\fI\,BRANCH\/\fR
submit for review on this target branch
.TP
\fB\-n\fR, \fB\-\-dry\-run\fR
do everything except actually upload the CL
.TP
\fB\-y\fR, \fB\-\-yes\fR
answer yes to all safe prompts
.TP
\fB\-\-no\-cert\-checks\fR
disable verifying ssl certs (unsafe)
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.SS pre\-upload hooks:
.TP
\fB\-\-no\-verify\fR
Do not run the pre\-upload hook.
.TP
\fB\-\-verify\fR
Run the pre\-upload hook without prompting.
.TP
\fB\-\-ignore\-hooks\fR
Do not abort if pre\-upload hooks fail.
.PP
Run `repo help upload` to view the detailed manual.
.SH DETAILS
.PP
The 'repo upload' command is used to send changes to the Gerrit Code Review
system. It searches for topic branches in local projects that have not yet been
published for review. If multiple topic branches are found, 'repo upload' opens
an editor to allow the user to select which branches to upload.
.PP
\&'repo upload' searches for uploadable changes in all projects listed at the
command line. Projects can be specified either by name, or by a relative or
absolute path to the project's local directory. If no projects are specified,
\&'repo upload' will search for uploadable changes in all projects listed in the
manifest.
.PP
If the \fB\-\-reviewers\fR or \fB\-\-cc\fR options are passed, those emails are added to the
respective list of users, and emails are sent to any new users. Users passed as
\fB\-\-reviewers\fR must already be registered with the code review system, or the
upload will fail.
.PP
Configuration
.PP
review.URL.autoupload:
.PP
To disable the "Upload ... (y/N)?" prompt, you can set a per\-project or global
Git configuration option. If review.URL.autoupload is set to "true" then repo
will assume you always answer "y" at the prompt, and will not prompt you
further. If it is set to "false" then repo will assume you always answer "n",
and will abort.
.PP
review.URL.autoreviewer:
.PP
To automatically append a user or mailing list to reviews, you can set a
per\-project or global Git option to do so.
.PP
review.URL.autocopy:
.PP
To automatically copy a user or mailing list to all uploaded reviews, you can
set a per\-project or global Git option to do so. Specifically,
review.URL.autocopy can be set to a comma separated list of reviewers who you
always want copied on all uploads with a non\-empty \fB\-\-re\fR argument.
.PP
review.URL.username:
.PP
Override the username used to connect to Gerrit Code Review. By default the
local part of the email address is used.
.PP
The URL must match the review URL listed in the manifest XML file, or in the
\&.git/config within the project. For example:
.IP
[remote "origin"]
.IP
url = git://git.example.com/project.git
review = http://review.example.com/
.IP
[review "http://review.example.com/"]
.IP
autoupload = true
autocopy = johndoe@company.com,my\-team\-alias@company.com
.PP
review.URL.uploadtopic:
.PP
To add a topic branch whenever uploading a commit, you can set a per\-project or
global Git option to do so. If review.URL.uploadtopic is set to "true" then repo
will assume you always want the equivalent of the \fB\-t\fR option to the repo command.
If unset or set to "false" then repo will make use of only the command line
option.
.PP
review.URL.uploadhashtags:
.PP
To add hashtags whenever uploading a commit, you can set a per\-project or global
Git option to do so. The value of review.URL.uploadhashtags will be used as
comma delimited hashtags like the \fB\-\-hashtag\fR option.
.PP
review.URL.uploadlabels:
.PP
To add labels whenever uploading a commit, you can set a per\-project or global
Git option to do so. The value of review.URL.uploadlabels will be used as comma
delimited labels like the \fB\-\-label\fR option.
.PP
review.URL.uploadnotify:
.PP
Control e\-mail notifications when uploading.
https://gerrit\-review.googlesource.com/Documentation/user\-upload.html#notify
.PP
References
.PP
Gerrit Code Review: https://www.gerritcodereview.com/

24
man/repo-version.1 Normal file
View File

@ -0,0 +1,24 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo version" "Repo Manual"
.SH NAME
repo \- repo version - manual page for repo version
.SH SYNOPSIS
.B repo
\fI\,version\/\fR
.SH DESCRIPTION
Summary
.PP
Display the version of repo
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.SS Logging options:
.TP
\fB\-v\fR, \fB\-\-verbose\fR
show all output
.TP
\fB\-q\fR, \fB\-\-quiet\fR
only show errors
.PP
Run `repo help version` to view the detailed manual.

133
man/repo.1 Normal file
View File

@ -0,0 +1,133 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
.TH REPO "1" "July 2021" "repo" "Repo Manual"
.SH NAME
repo \- repository management tool built on top of git
.SH SYNOPSIS
.B repo
[\fI\,-p|--paginate|--no-pager\/\fR] \fI\,COMMAND \/\fR[\fI\,ARGS\/\fR]
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
show this help message and exit
.TP
\fB\-\-help\-all\fR
show this help message with all subcommands and exit
.TP
\fB\-p\fR, \fB\-\-paginate\fR
display command output in the pager
.TP
\fB\-\-no\-pager\fR
disable the pager
.TP
\fB\-\-color\fR=\fI\,COLOR\/\fR
control color usage: auto, always, never
.TP
\fB\-\-trace\fR
trace git command execution (REPO_TRACE=1)
.TP
\fB\-\-trace\-python\fR
trace python command execution
.TP
\fB\-\-time\fR
time repo command execution
.TP
\fB\-\-version\fR
display this version of repo
.TP
\fB\-\-show\-toplevel\fR
display the path of the top\-level directory of the
repo client checkout
.TP
\fB\-\-event\-log\fR=\fI\,EVENT_LOG\/\fR
filename of event log to append timeline to
.TP
\fB\-\-git\-trace2\-event\-log\fR=\fI\,GIT_TRACE2_EVENT_LOG\/\fR
directory to write git trace2 event log to
.SS "The complete list of recognized repo commands are:"
.TP
abandon
Permanently abandon a development branch
.TP
branch
View current topic branches
.TP
branches
View current topic branches
.TP
checkout
Checkout a branch for development
.TP
cherry\-pick
Cherry\-pick a change.
.TP
diff
Show changes between commit and working tree
.TP
diffmanifests
Manifest diff utility
.TP
download
Download and checkout a change
.TP
forall
Run a shell command in each project
.TP
gitc\-delete
Delete a GITC Client.
.TP
gitc\-init
Initialize a GITC Client.
.TP
grep
Print lines matching a pattern
.TP
help
Display detailed help on a command
.TP
info
Get info on the manifest branch, current branch or unmerged branches
.TP
init
Initialize a repo client checkout in the current directory
.TP
list
List projects and their associated directories
.TP
manifest
Manifest inspection utility
.TP
overview
Display overview of unmerged project branches
.TP
prune
Prune (delete) already merged topics
.TP
rebase
Rebase local branches on upstream branch
.TP
selfupdate
Update repo to the latest version
.TP
smartsync
Update working tree to the latest known good revision
.TP
stage
Stage file(s) for commit
.TP
start
Start a new branch for development
.TP
status
Show the working tree status
.TP
sync
Update working tree to the latest revision
.TP
upload
Upload changes for code review
.TP
version
Display the version of repo
.PP
See 'repo help <command>' for more information on a specific command.
Bug reports: https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue

View File

@ -25,7 +25,7 @@ import gitc_utils
from git_config import GitConfig, IsId
from git_refs import R_HEADS, HEAD
import platform_utils
from project import RemoteSpec, Project, MetaProject
from project import Annotation, RemoteSpec, Project, MetaProject
from error import (ManifestParseError, ManifestInvalidPathError,
ManifestInvalidRevisionError)
from wrapper import Wrapper
@ -149,16 +149,18 @@ class _XmlRemote(object):
self.reviewUrl = review
self.revision = revision
self.resolvedFetchUrl = self._resolveFetchUrl()
self.annotations = []
def __eq__(self, other):
if not isinstance(other, _XmlRemote):
return False
return self.__dict__ == other.__dict__
return (sorted(self.annotations) == sorted(other.annotations) and
self.name == other.name and self.fetchUrl == other.fetchUrl and
self.pushUrl == other.pushUrl and self.remoteAlias == other.remoteAlias
and self.reviewUrl == other.reviewUrl and self.revision == other.revision)
def __ne__(self, other):
if not isinstance(other, _XmlRemote):
return True
return self.__dict__ != other.__dict__
return not self.__eq__(other)
def _resolveFetchUrl(self):
if self.fetchUrl is None:
@ -191,6 +193,9 @@ class _XmlRemote(object):
orig_name=self.name,
fetchUrl=self.fetchUrl)
def AddAnnotation(self, name, value, keep):
self.annotations.append(Annotation(name, value, keep))
class XmlManifest(object):
"""manages the repo configuration file"""
@ -265,8 +270,7 @@ class XmlManifest(object):
self.Override(name)
# Old versions of repo would generate symlinks we need to clean up.
if os.path.lexists(self.manifestFile):
platform_utils.remove(self.manifestFile)
platform_utils.remove(self.manifestFile, missing_ok=True)
# This file is interpreted as if it existed inside the manifest repo.
# That allows us to use <include> with the relative file name.
with open(self.manifestFile, 'w') as fp:
@ -300,6 +304,13 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
if r.revision is not None:
e.setAttribute('revision', r.revision)
for a in r.annotations:
if a.keep == 'true':
ae = doc.createElement('annotation')
ae.setAttribute('name', a.name)
ae.setAttribute('value', a.value)
e.appendChild(ae)
def _ParseList(self, field):
"""Parse fields that contain flattened lists.
@ -495,6 +506,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
if not d.remote or remote.orig_name != remoteName:
remoteName = remote.orig_name
e.setAttribute('remote', remoteName)
revision = remote.revision or d.revisionExpr
if not revision or revision != self._superproject['revision']:
e.setAttribute('revision', self._superproject['revision'])
root.appendChild(e)
if self._contactinfo.bugurl != Wrapper().BUG_URL:
@ -625,6 +639,13 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
'repo.partialcloneexclude') or ''
return set(x.strip() for x in exclude.split(','))
@property
def UseLocalManifests(self):
return self._load_local_manifests
def SetUseLocalManifests(self, value):
self._load_local_manifests = value
@property
def HasLocalManifests(self):
return self._load_local_manifests and self.local_manifests
@ -833,6 +854,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
for subproject in project.subprojects:
recursively_add_projects(subproject)
repo_hooks_project = None
enabled_repo_hooks = None
for node in itertools.chain(*node_list):
if node.nodeName == 'project':
project = self._ParseProject(node)
@ -845,6 +868,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
'project: %s' % name)
path = node.getAttribute('path')
dest_path = node.getAttribute('dest-path')
groups = node.getAttribute('groups')
if groups:
groups = self._ParseList(groups)
@ -853,46 +877,37 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
if remote:
remote = self._get_remote(node)
named_projects = self._projects[name]
if dest_path and not path and len(named_projects) > 1:
raise ManifestParseError('extend-project cannot use dest-path when '
'matching multiple projects: %s' % name)
for p in self._projects[name]:
if path and p.relpath != path:
continue
if groups:
p.groups.extend(groups)
if revision:
p.revisionExpr = revision
if IsId(revision):
p.revisionId = revision
else:
p.revisionId = None
p.SetRevision(revision)
if remote:
p.remote = remote.ToRemoteSpec(name)
if node.nodeName == 'repo-hooks':
# Get the name of the project and the (space-separated) list of enabled.
repo_hooks_project = self._reqatt(node, 'in-project')
enabled_repo_hooks = self._ParseList(self._reqatt(node, 'enabled-list'))
if dest_path:
del self._paths[p.relpath]
relpath, worktree, gitdir, objdir, _ = self.GetProjectPaths(name, dest_path)
p.UpdatePaths(relpath, worktree, gitdir, objdir)
self._paths[p.relpath] = p
if node.nodeName == 'repo-hooks':
# Only one project can be the hooks project
if self._repo_hooks_project is not None:
if repo_hooks_project is not None:
raise ManifestParseError(
'duplicate repo-hooks in %s' %
(self.manifestFile))
# Store a reference to the Project.
try:
repo_hooks_projects = self._projects[repo_hooks_project]
except KeyError:
raise ManifestParseError(
'project %s not found for repo-hooks' %
(repo_hooks_project))
if len(repo_hooks_projects) != 1:
raise ManifestParseError(
'internal error parsing repo-hooks in %s' %
(self.manifestFile))
self._repo_hooks_project = repo_hooks_projects[0]
# Store the enabled hooks in the Project object.
self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks
# Get the name of the project and the (space-separated) list of enabled.
repo_hooks_project = self._reqatt(node, 'in-project')
enabled_repo_hooks = self._ParseList(self._reqatt(node, 'enabled-list'))
if node.nodeName == 'superproject':
name = self._reqatt(node, 'name')
# There can only be one superproject.
@ -910,6 +925,13 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
raise ManifestParseError("no remote for superproject %s within %s" %
(name, self.manifestFile))
self._superproject['remote'] = remote.ToRemoteSpec(name)
revision = node.getAttribute('revision') or remote.revision
if not revision:
revision = self._default.revisionExpr
if not revision:
raise ManifestParseError('no revision for superproject %s within %s' %
(name, self.manifestFile))
self._superproject['revision'] = revision
if node.nodeName == 'contactinfo':
bugurl = self._reqatt(node, 'bugurl')
# This element can be repeated, later entries will clobber earlier ones.
@ -918,18 +940,36 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
if node.nodeName == 'remove-project':
name = self._reqatt(node, 'name')
if name not in self._projects:
if name in self._projects:
for p in self._projects[name]:
del self._paths[p.relpath]
del self._projects[name]
# If the manifest removes the hooks project, treat it as if it deleted
# the repo-hooks element too.
if repo_hooks_project == name:
repo_hooks_project = None
elif not XmlBool(node, 'optional', False):
raise ManifestParseError('remove-project element specifies non-existent '
'project: %s' % name)
for p in self._projects[name]:
del self._paths[p.relpath]
del self._projects[name]
# Store repo hooks project information.
if repo_hooks_project:
# Store a reference to the Project.
try:
repo_hooks_projects = self._projects[repo_hooks_project]
except KeyError:
raise ManifestParseError(
'project %s not found for repo-hooks' %
(repo_hooks_project))
# If the manifest removes the hooks project, treat it as if it deleted
# the repo-hooks element too.
if self._repo_hooks_project and (self._repo_hooks_project.name == name):
self._repo_hooks_project = None
if len(repo_hooks_projects) != 1:
raise ManifestParseError(
'internal error parsing repo-hooks in %s' %
(self.manifestFile))
self._repo_hooks_project = repo_hooks_projects[0]
# Store the enabled hooks in the Project object.
self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks
def _AddMetaProjectMirror(self, m):
name = None
@ -988,7 +1028,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
if revision == '':
revision = None
manifestUrl = self.manifestProject.config.GetString('remote.origin.url')
return _XmlRemote(name, alias, fetch, pushUrl, manifestUrl, review, revision)
remote = _XmlRemote(name, alias, fetch, pushUrl, manifestUrl, review, revision)
for n in node.childNodes:
if n.nodeName == 'annotation':
self._ParseAnnotation(remote, n)
return remote
def _ParseDefault(self, node):
"""
@ -1355,7 +1402,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
self._ValidateFilePaths('linkfile', src, dest)
project.AddLinkFile(src, dest, self.topdir)
def _ParseAnnotation(self, project, node):
def _ParseAnnotation(self, element, node):
name = self._reqatt(node, 'name')
value = self._reqatt(node, 'value')
try:
@ -1365,7 +1412,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
if keep != "true" and keep != "false":
raise ManifestParseError('optional "keep" attribute must be '
'"true" or "false"')
project.AddAnnotation(name, value, keep)
element.AddAnnotation(name, value, keep)
def _get_remote(self, node):
name = node.getAttribute('remote')

View File

@ -124,31 +124,30 @@ def rename(src, dst):
else:
raise
else:
os.rename(src, dst)
shutil.move(src, dst)
def remove(path):
def remove(path, missing_ok=False):
"""Remove (delete) the file path. This is a replacement for os.remove that
allows deleting read-only files on Windows, with support for long paths and
for deleting directory symbolic links.
Availability: Unix, Windows."""
if isWindows():
longpath = _makelongpath(path)
try:
os.remove(longpath)
except OSError as e:
if e.errno == errno.EACCES:
os.chmod(longpath, stat.S_IWRITE)
# Directory symbolic links must be deleted with 'rmdir'.
if islink(longpath) and isdir(longpath):
os.rmdir(longpath)
else:
os.remove(longpath)
longpath = _makelongpath(path) if isWindows() else path
try:
os.remove(longpath)
except OSError as e:
if e.errno == errno.EACCES:
os.chmod(longpath, stat.S_IWRITE)
# Directory symbolic links must be deleted with 'rmdir'.
if islink(longpath) and isdir(longpath):
os.rmdir(longpath)
else:
raise
else:
os.remove(path)
os.remove(longpath)
elif missing_ok and e.errno == errno.ENOENT:
pass
else:
raise
def walk(top, topdown=True, onerror=None, followlinks=False):

View File

@ -251,13 +251,29 @@ class DiffColoring(Coloring):
self.fail = self.printer('fail', fg='red')
class _Annotation(object):
class Annotation(object):
def __init__(self, name, value, keep):
self.name = name
self.value = value
self.keep = keep
def __eq__(self, other):
if not isinstance(other, Annotation):
return False
return self.__dict__ == other.__dict__
def __lt__(self, other):
# This exists just so that lists of Annotation objects can be sorted, for
# use in comparisons.
if not isinstance(other, Annotation):
raise ValueError('comparison is not between two Annotation objects')
if self.name == other.name:
if self.value == other.value:
return self.keep < other.keep
return self.value < other.value
return self.name < other.name
def _SafeExpandPath(base, subpath, skipfinal=False):
"""Make sure |subpath| is completely safe under |base|.
@ -503,21 +519,8 @@ class Project(object):
self.client = self.manifest = manifest
self.name = name
self.remote = remote
self.gitdir = gitdir.replace('\\', '/')
self.objdir = objdir.replace('\\', '/')
if worktree:
self.worktree = os.path.normpath(worktree).replace('\\', '/')
else:
self.worktree = None
self.relpath = relpath
self.revisionExpr = revisionExpr
if revisionId is None \
and revisionExpr \
and IsId(revisionExpr):
self.revisionId = revisionExpr
else:
self.revisionId = revisionId
self.UpdatePaths(relpath, worktree, gitdir, objdir)
self.SetRevision(revisionExpr, revisionId=revisionId)
self.rebase = rebase
self.groups = groups
@ -540,16 +543,6 @@ class Project(object):
self.copyfiles = []
self.linkfiles = []
self.annotations = []
self.config = GitConfig.ForRepository(gitdir=self.gitdir,
defaults=self.client.globalConfig)
if self.worktree:
self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir)
else:
self.work_git = None
self.bare_git = self._GitGetByExec(self, bare=True, gitdir=gitdir)
self.bare_ref = GitRefs(gitdir)
self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=objdir)
self.dest_branch = dest_branch
self.old_revision = old_revision
@ -557,6 +550,35 @@ class Project(object):
# project containing repo hooks.
self.enabled_repo_hooks = []
def SetRevision(self, revisionExpr, revisionId=None):
"""Set revisionId based on revision expression and id"""
self.revisionExpr = revisionExpr
if revisionId is None and revisionExpr and IsId(revisionExpr):
self.revisionId = self.revisionExpr
else:
self.revisionId = revisionId
def UpdatePaths(self, relpath, worktree, gitdir, objdir):
"""Update paths used by this project"""
self.gitdir = gitdir.replace('\\', '/')
self.objdir = objdir.replace('\\', '/')
if worktree:
self.worktree = os.path.normpath(worktree).replace('\\', '/')
else:
self.worktree = None
self.relpath = relpath
self.config = GitConfig.ForRepository(gitdir=self.gitdir,
defaults=self.manifest.globalConfig)
if self.worktree:
self.work_git = self._GitGetByExec(self, bare=False, gitdir=self.gitdir)
else:
self.work_git = None
self.bare_git = self._GitGetByExec(self, bare=True, gitdir=self.gitdir)
self.bare_ref = GitRefs(self.gitdir)
self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=self.objdir)
@property
def Derived(self):
return self.is_derived
@ -1166,10 +1188,8 @@ class Project(object):
self._InitMRef()
else:
self._InitMirrorHead()
try:
platform_utils.remove(os.path.join(self.gitdir, 'FETCH_HEAD'))
except OSError:
pass
platform_utils.remove(os.path.join(self.gitdir, 'FETCH_HEAD'),
missing_ok=True)
return True
def PostRepoUpgrade(self):
@ -1216,7 +1236,7 @@ class Project(object):
(self.revisionExpr, self.name))
def SetRevisionId(self, revisionId):
if self.clone_depth or self.manifest.manifestProject.config.GetString('repo.depth'):
if self.revisionExpr:
self.upstream = self.revisionExpr
self.revisionId = revisionId
@ -1448,7 +1468,7 @@ class Project(object):
self.linkfiles.append(_LinkFile(self.worktree, src, topdir, dest))
def AddAnnotation(self, name, value, keep):
self.annotations.append(_Annotation(name, value, keep))
self.annotations.append(Annotation(name, value, keep))
def DownloadPatchSet(self, change_id, patch_id):
"""Download a single patch set of a single change to FETCH_HEAD.
@ -1967,6 +1987,11 @@ class Project(object):
# throws an error.
self.bare_git.rev_list('-1', '--missing=allow-any',
'%s^0' % self.revisionExpr, '--')
if self.upstream:
rev = self.GetRemote(self.remote.name).ToLocal(self.upstream)
self.bare_git.rev_list('-1', '--missing=allow-any',
'%s^0' % rev, '--')
self.bare_git.merge_base('--is-ancestor', self.revisionExpr, rev)
return True
except GitError:
# There is no such persistent revision. We have to fetch it.
@ -2286,15 +2311,12 @@ class Project(object):
cmd.append('+refs/tags/*:refs/tags/*')
ok = GitCommand(self, cmd, bare=True).Wait() == 0
if os.path.exists(bundle_dst):
platform_utils.remove(bundle_dst)
if os.path.exists(bundle_tmp):
platform_utils.remove(bundle_tmp)
platform_utils.remove(bundle_dst, missing_ok=True)
platform_utils.remove(bundle_tmp, missing_ok=True)
return ok
def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet, verbose):
if os.path.exists(dstPath):
platform_utils.remove(dstPath)
platform_utils.remove(dstPath, missing_ok=True)
cmd = ['curl', '--fail', '--output', tmpPath, '--netrc', '--location']
if quiet:
@ -2718,10 +2740,7 @@ class Project(object):
# If the source file doesn't exist, ensure the destination
# file doesn't either.
if name in symlink_files and not os.path.lexists(src):
try:
platform_utils.remove(dst)
except OSError:
pass
platform_utils.remove(dst, missing_ok=True)
except OSError as e:
if e.errno == errno.EPERM:

View File

@ -20,6 +20,7 @@ This is intended to be run only by the official Repo release managers.
import argparse
import os
import re
import subprocess
import sys
@ -49,18 +50,37 @@ def check(opts):
util.run(opts, ['gpg', '--verify', f'{opts.launcher}.asc'])
def postmsg(opts):
def get_version(opts):
"""Get the version from |launcher|."""
# Make sure we don't search $PATH when signing the "repo" file in the cwd.
launcher = os.path.join('.', opts.launcher)
cmd = [launcher, '--version']
ret = util.run(opts, cmd, encoding='utf-8', stdout=subprocess.PIPE)
m = re.search(r'repo launcher version ([0-9.]+)', ret.stdout)
if not m:
sys.exit(f'{opts.launcher}: unable to detect repo version')
return m.group(1)
def postmsg(opts, version):
"""Helpful info to show at the end for release manager."""
print(f"""
Repo launcher bucket:
gs://git-repo-downloads/
To upload this launcher directly:
gsutil cp -a public-read {opts.launcher} {opts.launcher}.asc gs://git-repo-downloads/
You should first upload it with a specific version:
gsutil cp -a public-read {opts.launcher} gs://git-repo-downloads/repo-{version}
gsutil cp -a public-read {opts.launcher}.asc gs://git-repo-downloads/repo-{version}.asc
NB: You probably want to upload it with a specific version first, e.g.:
gsutil cp -a public-read {opts.launcher} gs://git-repo-downloads/repo-3.0
gsutil cp -a public-read {opts.launcher}.asc gs://git-repo-downloads/repo-3.0.asc
Then to make it the public default:
gsutil cp -a public-read gs://git-repo-downloads/repo-{version} gs://git-repo-downloads/repo
gsutil cp -a public-read gs://git-repo-downloads/repo-{version}.asc gs://git-repo-downloads/repo.asc
NB: If a rollback is necessary, the GS bucket archives old versions, and may be
accessed by specifying their unique id number.
gsutil ls -la gs://git-repo-downloads/repo gs://git-repo-downloads/repo.asc
gsutil cp -a public-read gs://git-repo-downloads/repo#<unique id> gs://git-repo-downloads/repo
gsutil cp -a public-read gs://git-repo-downloads/repo.asc#<unique id> gs://git-repo-downloads/repo.asc
""")
@ -103,9 +123,10 @@ def main(argv):
opts.keys = [util.KEYID_DSA, util.KEYID_RSA, util.KEYID_ECC]
util.import_release_key(opts)
version = get_version(opts)
sign(opts)
check(opts)
postmsg(opts)
postmsg(opts, version)
return 0

102
release/update-manpages Executable file
View File

@ -0,0 +1,102 @@
#!/usr/bin/env python3
# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helper tool for generating manual page for all repo commands.
This is intended to be run before every official Repo release.
"""
from pathlib import Path
from functools import partial
import argparse
import multiprocessing
import os
import re
import shutil
import subprocess
import sys
import tempfile
TOPDIR = Path(__file__).resolve().parent.parent
MANDIR = TOPDIR.joinpath('man')
# Load repo local modules.
sys.path.insert(0, str(TOPDIR))
from git_command import RepoSourceVersion
import subcmds
def worker(cmd, **kwargs):
subprocess.run(cmd, **kwargs)
def main(argv):
parser = argparse.ArgumentParser(description=__doc__)
opts = parser.parse_args(argv)
if not shutil.which('help2man'):
sys.exit('Please install help2man to continue.')
# Let repo know we're generating man pages so it can avoid some dynamic
# behavior (like probing active number of CPUs). We use a weird name &
# value to make it less likely for users to set this var themselves.
os.environ['_REPO_GENERATE_MANPAGES_'] = ' indeed! '
# "repo branch" is an alias for "repo branches".
del subcmds.all_commands['branch']
(MANDIR / 'repo-branch.1').write_text('.so man1/repo-branches.1')
version = RepoSourceVersion()
cmdlist = [['help2man', '-N', '-n', f'repo {cmd} - manual page for repo {cmd}',
'-S', f'repo {cmd}', '-m', 'Repo Manual', f'--version-string={version}',
'-o', MANDIR.joinpath(f'repo-{cmd}.1.tmp'), TOPDIR.joinpath('repo'),
'-h', f'help {cmd}'] for cmd in subcmds.all_commands]
cmdlist.append(['help2man', '-N', '-n', 'repository management tool built on top of git',
'-S', 'repo', '-m', 'Repo Manual', f'--version-string={version}',
'-o', MANDIR.joinpath('repo.1.tmp'), TOPDIR.joinpath('repo'),
'-h', '--help-all'])
with tempfile.TemporaryDirectory() as tempdir:
repo_dir = Path(tempdir) / '.repo'
repo_dir.mkdir()
(repo_dir / 'repo').symlink_to(TOPDIR)
# Run all cmd in parallel, and wait for them to finish.
with multiprocessing.Pool() as pool:
pool.map(partial(worker, cwd=tempdir, check=True), cmdlist)
regex = (
(r'(It was generated by help2man) [0-9.]+', '\g<1>.'),
(r'^\.IP\n(.*:)\n', '.SS \g<1>\n'),
(r'^\.PP\nDescription', '.SH DETAILS'),
)
for tmp_path in MANDIR.glob('*.1.tmp'):
path = tmp_path.parent / tmp_path.stem
old_data = path.read_text() if path.exists() else ''
data = tmp_path.read_text()
tmp_path.unlink()
for pattern, replacement in regex:
data = re.sub(pattern, replacement, data, flags=re.M)
# If the only thing that changed was the date, don't refresh. This avoids
# a lot of noise when only one file actually updates.
old_data = re.sub(r'^(\.TH REPO "1" ")([^"]+)', r'\1', old_data, flags=re.M)
new_data = re.sub(r'^(\.TH REPO "1" ")([^"]+)', r'\1', data, flags=re.M)
if old_data != new_data:
path.write_text(data)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

6
repo
View File

@ -149,7 +149,7 @@ if not REPO_REV:
BUG_URL = 'https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue'
# increment this whenever we make important changes to this script
VERSION = (2, 15)
VERSION = (2, 17)
# increment this if the MAINTAINER_KEYS block is modified
KEYRING_VERSION = (2, 3)
@ -312,6 +312,10 @@ def InitParser(parser, gitc_init=False):
metavar='PLATFORM')
group.add_option('--submodules', action='store_true',
help='sync any submodules associated with the manifest repo')
group.add_option('--standalone-manifest', action='store_true',
help='download the manifest as a static file '
'rather then create a git checkout of '
'the manifest repo')
# Options that only affect manifest project, and not any of the projects
# specified in the manifest itself.

View File

@ -50,14 +50,21 @@ Displays detailed usage information about a command.
def _PrintAllCommands(self):
print('usage: repo COMMAND [ARGS]')
self.PrintAllCommandsBody()
def PrintAllCommandsBody(self):
print('The complete list of recognized repo commands are:')
commandNames = list(sorted(all_commands))
self._PrintCommands(commandNames)
print("See 'repo help <command>' for more information on a "
'specific command.')
print('Bug reports:', Wrapper().BUG_URL)
def _PrintCommonCommands(self):
print('usage: repo COMMAND [ARGS]')
self.PrintCommonCommandsBody()
def PrintCommonCommandsBody(self):
print('The most commonly used repo commands are:')
def gitc_supported(cmd):

View File

@ -15,6 +15,7 @@
import os
import platform
import re
import subprocess
import sys
import urllib.parse
@ -24,6 +25,7 @@ from error import ManifestParseError
from project import SyncBuffer
from git_config import GitConfig
from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD
import fetch
import git_superproject
import platform_utils
from wrapper import Wrapper
@ -53,6 +55,12 @@ The optional -m argument can be used to specify an alternate manifest
to be used. If no manifest is specified, the manifest default.xml
will be used.
If the --standalone-manifest argument is set, the manifest will be downloaded
directly from the specified --manifest-url as a static file (rather than
setting up a manifest git checkout). With --standalone-manifest, the manifest
will be fully static and will not be re-downloaded during subsesquent
`repo init` and `repo sync` calls.
The --reference option can be used to point to a directory that
has the content of a --mirror sync. This will make the working
directory use as much data as possible from the local reference
@ -100,14 +108,39 @@ to update the working directory files.
quiet=opt.quiet)
sync_result = superproject.Sync()
if not sync_result.success:
print('error: git update of superproject failed', file=sys.stderr)
if sync_result.fatal:
print('warning: git update of superproject failed, repo sync will not '
'use superproject to fetch source; while this error is not fatal, '
'and you can continue to run repo sync, please run repo init with '
'the --no-use-superproject option to stop seeing this warning',
file=sys.stderr)
if sync_result.fatal and opt.use_superproject is not None:
sys.exit(1)
def _SyncManifest(self, opt):
m = self.manifest.manifestProject
is_new = not m.Exists
# If repo has already been initialized, we take -u with the absence of
# --standalone-manifest to mean "transition to a standard repo set up",
# which necessitates starting fresh.
# If --standalone-manifest is set, we always tear everything down and start
# anew.
if not is_new:
was_standalone_manifest = m.config.GetString('manifest.standalone')
if was_standalone_manifest and not opt.manifest_url:
print('fatal: repo was initialized with a standlone manifest, '
'cannot be re-initialized without --manifest-url/-u')
sys.exit(1)
if opt.standalone_manifest or (
was_standalone_manifest and opt.manifest_url):
m.config.ClearCache()
if m.gitdir and os.path.exists(m.gitdir):
platform_utils.rmtree(m.gitdir)
if m.worktree and os.path.exists(m.worktree):
platform_utils.rmtree(m.worktree)
is_new = not m.Exists
if is_new:
if not opt.manifest_url:
print('fatal: manifest url is required.', file=sys.stderr)
@ -132,6 +165,21 @@ to update the working directory files.
m._InitGitDir(mirror_git=mirrored_manifest_git)
# If standalone_manifest is set, mark the project as "standalone" -- we'll
# still do much of the manifests.git set up, but will avoid actual syncs to
# a remote.
standalone_manifest = False
if opt.standalone_manifest:
standalone_manifest = True
m.config.SetString('manifest.standalone', opt.manifest_url)
elif not opt.manifest_url and not opt.manifest_branch:
# If -u is set and --standalone-manifest is not, then we're not in
# standalone mode. Otherwise, use config to infer what we were in the last
# init.
standalone_manifest = bool(m.config.GetString('manifest.standalone'))
if not standalone_manifest:
m.config.SetString('manifest.standalone', None)
self._ConfigureDepth(opt)
# Set the remote URL before the remote branch as we might need it below.
@ -141,22 +189,23 @@ to update the working directory files.
r.ResetFetch()
r.Save()
if opt.manifest_branch:
if opt.manifest_branch == 'HEAD':
opt.manifest_branch = m.ResolveRemoteHead()
if opt.manifest_branch is None:
print('fatal: unable to resolve HEAD', file=sys.stderr)
sys.exit(1)
m.revisionExpr = opt.manifest_branch
else:
if is_new:
default_branch = m.ResolveRemoteHead()
if default_branch is None:
# If the remote doesn't have HEAD configured, default to master.
default_branch = 'refs/heads/master'
m.revisionExpr = default_branch
if not standalone_manifest:
if opt.manifest_branch:
if opt.manifest_branch == 'HEAD':
opt.manifest_branch = m.ResolveRemoteHead()
if opt.manifest_branch is None:
print('fatal: unable to resolve HEAD', file=sys.stderr)
sys.exit(1)
m.revisionExpr = opt.manifest_branch
else:
m.PreSync()
if is_new:
default_branch = m.ResolveRemoteHead()
if default_branch is None:
# If the remote doesn't have HEAD configured, default to master.
default_branch = 'refs/heads/master'
m.revisionExpr = default_branch
else:
m.PreSync()
groups = re.split(r'[,\s]+', opt.groups)
all_platforms = ['linux', 'darwin', 'windows']
@ -246,6 +295,16 @@ to update the working directory files.
if opt.use_superproject is not None:
m.config.SetBoolean('repo.superproject', opt.use_superproject)
if standalone_manifest:
if is_new:
manifest_name = 'default.xml'
manifest_data = fetch.fetch_file(opt.manifest_url)
dest = os.path.join(m.worktree, manifest_name)
os.makedirs(os.path.dirname(dest), exist_ok=True)
with open(dest, 'wb') as f:
f.write(manifest_data)
return
if not m.Sync_NetworkHalf(is_new=is_new, quiet=opt.quiet, verbose=opt.verbose,
clone_bundle=opt.clone_bundle,
current_branch_only=opt.current_branch_only,
@ -422,6 +481,11 @@ to update the working directory files.
if opt.archive and opt.mirror:
self.OptionParser.error('--mirror and --archive cannot be used together.')
if opt.standalone_manifest and (
opt.manifest_branch or opt.manifest_name != 'default.xml'):
self.OptionParser.error('--manifest-branch and --manifest-name cannot'
' be used with --standalone-manifest.')
if args:
if opt.manifest_url:
self.OptionParser.error(

View File

@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from command import Command, MirrorSafeCommand
@ -43,20 +45,26 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
p.add_option('-a', '--all',
action='store_true',
help='show projects regardless of checkout state')
p.add_option('-f', '--fullpath',
dest='fullpath', action='store_true',
help='display the full work tree path instead of the relative path')
p.add_option('-n', '--name-only',
dest='name_only', action='store_true',
help='display only the name of the repository')
p.add_option('-p', '--path-only',
dest='path_only', action='store_true',
help='display only the path of the repository')
p.add_option('-f', '--fullpath',
dest='fullpath', action='store_true',
help='display the full work tree path instead of the relative path')
p.add_option('--relative-to', metavar='PATH',
help='display paths relative to this one (default: top of repo client checkout)')
def ValidateOptions(self, opt, args):
if opt.fullpath and opt.name_only:
self.OptionParser.error('cannot combine -f and -n')
# Resolve any symlinks so the output is stable.
if opt.relative_to:
opt.relative_to = os.path.realpath(opt.relative_to)
def Execute(self, opt, args):
"""List all projects and the associated directories.
@ -76,6 +84,8 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
def _getpath(x):
if opt.fullpath:
return x.worktree
if opt.relative_to:
return os.path.relpath(x.worktree, opt.relative_to)
return x.relpath
lines = []

View File

@ -70,6 +70,8 @@ to indicate the remote ref to push changes to via 'repo upload'.
help='output manifest in JSON format (experimental)')
p.add_option('--pretty', default=False, action='store_true',
help='format output for humans to read')
p.add_option('--no-local-manifests', default=False, action='store_true',
dest='ignore_local_manifests', help='ignore local manifests')
p.add_option('-o', '--output-file',
dest='output_file',
default='-',
@ -85,6 +87,9 @@ to indicate the remote ref to push changes to via 'repo upload'.
fd = sys.stdout
else:
fd = open(opt.output_file, 'w')
self.manifest.SetUseLocalManifests(not opt.ignore_local_manifests)
if opt.json:
print('warning: --json is experimental!', file=sys.stderr)
doc = self.manifest.ToDict(peg_rev=opt.peg_rev,

View File

@ -278,18 +278,11 @@ later is required to fix a server side protocol bug.
branch = branch[len(R_HEADS):]
return branch
def _UseSuperproject(self, opt):
"""Returns True if use-superproject option is enabled"""
if opt.use_superproject is not None:
return opt.use_superproject
else:
return self.manifest.manifestProject.config.GetBoolean('repo.superproject')
def _GetCurrentBranchOnly(self, opt):
"""Returns True if current-branch or use-superproject options are enabled."""
return opt.current_branch_only or self._UseSuperproject(opt)
return opt.current_branch_only or git_superproject.UseSuperproject(opt, self.manifest)
def _UpdateProjectsRevisionId(self, opt, args, load_local_manifests):
def _UpdateProjectsRevisionId(self, opt, args, load_local_manifests, superproject_logging_data):
"""Update revisionId of every project with the SHA from superproject.
This function updates each project's revisionId with SHA from superproject.
@ -300,26 +293,38 @@ later is required to fix a server side protocol bug.
args: Arguments to pass to GetProjects. See the GetProjects
docstring for details.
load_local_manifests: Whether to load local manifests.
superproject_logging_data: A dictionary of superproject data that is to be logged.
Returns:
Returns path to the overriding manifest file instead of None.
"""
print_messages = git_superproject.PrintMessages(opt, self.manifest)
superproject = git_superproject.Superproject(self.manifest,
self.repodir,
self.git_event_log,
quiet=opt.quiet)
quiet=opt.quiet,
print_messages=print_messages)
if opt.local_only:
manifest_path = superproject.manifest_path
if manifest_path:
self._ReloadManifest(manifest_path, load_local_manifests)
return manifest_path
all_projects = self.GetProjects(args,
missing_ok=True,
submodules_ok=opt.fetch_submodules)
update_result = superproject.UpdateProjectsRevisionId(all_projects)
manifest_path = update_result.manifest_path
superproject_logging_data['updatedrevisionid'] = bool(manifest_path)
if manifest_path:
self._ReloadManifest(manifest_path, load_local_manifests)
else:
print('error: Update of revsionId from superproject has failed. '
'Please resync with --no-use-superproject option',
file=sys.stderr)
if update_result.fatal:
if print_messages:
print('warning: Update of revisionId from superproject has failed, '
'repo sync will not use superproject to fetch the source. ',
'Please resync with the --no-use-superproject option to avoid this repo warning.',
file=sys.stderr)
if update_result.fatal and opt.use_superproject is not None:
sys.exit(1)
return manifest_path
@ -367,7 +372,7 @@ later is required to fix a server side protocol bug.
partial_clone_exclude=self.manifest.PartialCloneExclude)
output = buf.getvalue()
if opt.verbose and output:
if (opt.verbose or not success) and output:
print('\n' + output.rstrip())
if not success:
@ -600,7 +605,7 @@ later is required to fix a server side protocol bug.
pm = Progress('Garbage collecting', len(projects), delay=False, quiet=opt.quiet)
pm.update(inc=0, msg='prescan')
gc_gitdirs = {}
tidy_dirs = {}
for project in projects:
# Make sure pruning never kicks in with shared projects.
if (not project.use_git_worktrees and
@ -617,17 +622,29 @@ later is required to fix a server side protocol bug.
% (project.relpath,),
file=sys.stderr)
project.config.SetString('gc.pruneExpire', 'never')
gc_gitdirs[project.gitdir] = project.bare_git
pm.update(inc=len(projects) - len(gc_gitdirs), msg='warming up')
project.config.SetString('gc.autoDetach', 'false')
# Only call git gc once per objdir, but call pack-refs for the remainder.
if project.objdir not in tidy_dirs:
tidy_dirs[project.objdir] = (
True, # Run a full gc.
project.bare_git,
)
elif project.gitdir not in tidy_dirs:
tidy_dirs[project.gitdir] = (
False, # Do not run a full gc; just run pack-refs.
project.bare_git,
)
cpu_count = os.cpu_count()
jobs = min(self.jobs, cpu_count)
if jobs < 2:
for bare_git in gc_gitdirs.values():
for (run_gc, bare_git) in tidy_dirs.values():
pm.update(msg=bare_git._project.name)
bare_git.gc('--auto')
if run_gc:
bare_git.gc('--auto')
else:
bare_git.pack_refs()
pm.end()
return
@ -636,11 +653,14 @@ later is required to fix a server side protocol bug.
threads = set()
sem = _threading.Semaphore(jobs)
def GC(bare_git):
def tidy_up(run_gc, bare_git):
pm.start(bare_git._project.name)
try:
try:
bare_git.gc('--auto', config=config)
if run_gc:
bare_git.gc('--auto', config=config)
else:
bare_git.pack_refs(config=config)
except GitError:
err_event.set()
except Exception:
@ -650,11 +670,11 @@ later is required to fix a server side protocol bug.
pm.finish(bare_git._project.name)
sem.release()
for bare_git in gc_gitdirs.values():
for (run_gc, bare_git) in tidy_dirs.values():
if err_event.is_set() and opt.fail_fast:
break
sem.acquire()
t = _threading.Thread(target=GC, args=(bare_git,))
t = _threading.Thread(target=tidy_up, args=(run_gc, bare_git,))
t.daemon = True
threads.add(t)
t.start()
@ -762,13 +782,9 @@ later is required to fix a server side protocol bug.
set(new_copyfile_paths))
for need_remove_file in need_remove_files:
try:
platform_utils.remove(need_remove_file)
except OSError as e:
if e.errno == errno.ENOENT:
# Try to remove the updated copyfile or linkfile.
# So, if the file is not exist, nothing need to do.
pass
# Try to remove the updated copyfile or linkfile.
# So, if the file is not exist, nothing need to do.
platform_utils.remove(need_remove_file, missing_ok=True)
# Create copy-link-files.json, save dest path of "copyfile" and "linkfile".
with open(copylinkfile_path, 'w', encoding='utf-8') as fp:
@ -953,21 +969,28 @@ later is required to fix a server side protocol bug.
file=sys.stderr)
mp = self.manifest.manifestProject
mp.PreSync()
is_standalone_manifest = mp.config.GetString('manifest.standalone')
if not is_standalone_manifest:
mp.PreSync()
if opt.repo_upgraded:
_PostRepoUpgrade(self.manifest, quiet=opt.quiet)
if not opt.mp_update:
print('Skipping update of local manifest project.')
else:
elif not is_standalone_manifest:
self._UpdateManifestProject(opt, mp, manifest_name)
load_local_manifests = not self.manifest.HasLocalManifests
if self._UseSuperproject(opt):
new_manifest_name = self._UpdateProjectsRevisionId(opt, args, load_local_manifests)
if not new_manifest_name:
manifest_name = new_manifest_name
use_superproject = git_superproject.UseSuperproject(opt, self.manifest)
superproject_logging_data = {
'superproject': use_superproject,
'haslocalmanifests': bool(self.manifest.HasLocalManifests),
'hassuperprojecttag': bool(self.manifest.superproject),
}
if use_superproject:
manifest_name = self._UpdateProjectsRevisionId(
opt, args, load_local_manifests, superproject_logging_data) or opt.manifest_name
if self.gitc_manifest:
gitc_manifest_projects = self.GetProjects(args,
@ -1081,6 +1104,15 @@ later is required to fix a server side protocol bug.
file=sys.stderr)
sys.exit(1)
# Log the previous sync analysis state from the config.
self.git_event_log.LogDataConfigEvents(mp.config.GetSyncAnalysisStateData(),
'previous_sync_state')
# Update and log with the new sync analysis state.
mp.config.UpdateSyncAnalysisState(opt, superproject_logging_data)
self.git_event_log.LogDataConfigEvents(mp.config.GetSyncAnalysisStateData(),
'current_sync_state')
if not opt.quiet:
print('repo sync has finished successfully.')
@ -1152,10 +1184,7 @@ class _FetchTimes(object):
with open(self._path) as f:
self._times = json.load(f)
except (IOError, ValueError):
try:
platform_utils.remove(self._path)
except OSError:
pass
platform_utils.remove(self._path, missing_ok=True)
self._times = {}
def Save(self):
@ -1173,10 +1202,7 @@ class _FetchTimes(object):
with open(self._path, 'w') as f:
json.dump(self._times, f, indent=2)
except (IOError, TypeError):
try:
platform_utils.remove(self._path)
except OSError:
pass
platform_utils.remove(self._path, missing_ok=True)
# This is a replacement for xmlrpc.client.Transport using urllib2
# and supporting persistent-http[s]. It cannot change hosts from

View File

@ -168,6 +168,25 @@ class GitConfigReadWriteTests(unittest.TestCase):
config = self.get_config()
self.assertIsNone(config.GetBoolean('foo.bar'))
def test_GetSyncAnalysisStateData(self):
"""Test config entries with a sync state analysis data."""
superproject_logging_data = {}
superproject_logging_data['test'] = False
options = type('options', (object,), {})()
options.verbose = 'true'
options.mp_update = 'false'
TESTS = (
('superproject.test', 'false'),
('options.verbose', 'true'),
('options.mpupdate', 'false'),
('main.version', '1'),
)
self.config.UpdateSyncAnalysisState(options, superproject_logging_data)
sync_data = self.config.GetSyncAnalysisStateData()
for key, value in TESTS:
self.assertEqual(sync_data[f'{git_config.SYNC_STATE_PREFIX}{key}'], value)
self.assertTrue(sync_data[f'{git_config.SYNC_STATE_PREFIX}main.synctime'])
if __name__ == '__main__':
unittest.main()

View File

@ -157,7 +157,7 @@ class SuperprojectTestCase(unittest.TestCase):
""")
self._superproject = git_superproject.Superproject(manifest, self.repodir,
self.git_event_log)
with mock.patch.object(self._superproject, '_GetBranch', return_value='junk'):
with mock.patch.object(self._superproject, '_branch', 'junk'):
sync_result = self._superproject.Sync()
self.assertFalse(sync_result.success)
self.assertTrue(sync_result.fatal)
@ -203,7 +203,7 @@ class SuperprojectTestCase(unittest.TestCase):
project.SetRevisionId('ABCDEF')
# Create temporary directory so that it can write the file.
os.mkdir(self._superproject._superproject_path)
manifest_path = self._superproject._WriteManfiestFile()
manifest_path = self._superproject._WriteManifestFile()
self.assertIsNotNone(manifest_path)
with open(manifest_path, 'r') as fp:
manifest_xml_data = fp.read()
@ -213,7 +213,7 @@ class SuperprojectTestCase(unittest.TestCase):
'<remote fetch="http://localhost" name="default-remote"/>'
'<default remote="default-remote" revision="refs/heads/main"/>'
'<project groups="notdefault,platform-' + self.platform + '" '
'name="platform/art" path="art" revision="ABCDEF"/>'
'name="platform/art" path="art" revision="ABCDEF" upstream="refs/heads/main"/>'
'<superproject name="superproject"/>'
'</manifest>')
@ -242,7 +242,7 @@ class SuperprojectTestCase(unittest.TestCase):
'<default remote="default-remote" revision="refs/heads/main"/>'
'<project groups="notdefault,platform-' + self.platform + '" '
'name="platform/art" path="art" '
'revision="2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea"/>'
'revision="2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea" upstream="refs/heads/main"/>'
'<superproject name="superproject"/>'
'</manifest>')
@ -271,7 +271,7 @@ class SuperprojectTestCase(unittest.TestCase):
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="default-remote"/>'
'<default remote="default-remote" revision="refs/heads/main"/>'
'<project name="test-name" revision="ABCDEF"/>'
'<project name="test-name" revision="ABCDEF" upstream="refs/heads/main"/>'
'</manifest>')
def test_superproject_update_project_revision_id_from_local_manifest_group(self):
@ -294,8 +294,7 @@ class SuperprojectTestCase(unittest.TestCase):
self.git_event_log)
self.assertEqual(len(self._superproject._manifest.projects), 2)
projects = self._superproject._manifest.projects
data = ('160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00'
'160000 commit e9d25da64d8d365dbba7c8ee00fe8c4473fe9a06\tbootable/recovery\x00')
data = ('160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00')
with mock.patch.object(self._superproject, '_Init', return_value=True):
with mock.patch.object(self._superproject, '_Fetch', return_value=True):
with mock.patch.object(self._superproject,
@ -317,13 +316,61 @@ class SuperprojectTestCase(unittest.TestCase):
'<default remote="default-remote" revision="refs/heads/main"/>'
'<project groups="notdefault,platform-' + self.platform + '" '
'name="platform/art" path="art" '
'revision="2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea"/>'
'revision="2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea" upstream="refs/heads/main"/>'
'<project clone-depth="1" groups="' + local_group + '" '
'name="platform/vendor/x" path="vendor/x" remote="goog" '
'revision="master-with-vendor"/>'
'<superproject name="superproject"/>'
'</manifest>')
def test_superproject_update_project_revision_id_with_pinned_manifest(self):
"""Test update of commit ids of a pinned manifest."""
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<superproject name="superproject"/>
<project path="vendor/x" name="platform/vendor/x" revision="" />
<project path="vendor/y" name="platform/vendor/y"
revision="52d3c9f7c107839ece2319d077de0cd922aa9d8f" />
<project path="art" name="platform/art" groups="notdefault,platform-""" + self.platform + """
" /></manifest>
""")
self.maxDiff = None
self._superproject = git_superproject.Superproject(manifest, self.repodir,
self.git_event_log)
self.assertEqual(len(self._superproject._manifest.projects), 3)
projects = self._superproject._manifest.projects
data = ('160000 commit 2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea\tart\x00'
'160000 commit e9d25da64d8d365dbba7c8ee00fe8c4473fe9a06\tvendor/x\x00')
with mock.patch.object(self._superproject, '_Init', return_value=True):
with mock.patch.object(self._superproject, '_Fetch', return_value=True):
with mock.patch.object(self._superproject,
'_LsTree',
return_value=data):
# Create temporary directory so that it can write the file.
os.mkdir(self._superproject._superproject_path)
update_result = self._superproject.UpdateProjectsRevisionId(projects)
self.assertIsNotNone(update_result.manifest_path)
self.assertFalse(update_result.fatal)
with open(update_result.manifest_path, 'r') as fp:
manifest_xml_data = fp.read()
# Verify platform/vendor/x's project revision hasn't changed.
self.assertEqual(
sort_attributes(manifest_xml_data),
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="default-remote"/>'
'<default remote="default-remote" revision="refs/heads/main"/>'
'<project groups="notdefault,platform-' + self.platform + '" '
'name="platform/art" path="art" '
'revision="2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea" upstream="refs/heads/main"/>'
'<project name="platform/vendor/x" path="vendor/x" '
'revision="e9d25da64d8d365dbba7c8ee00fe8c4473fe9a06" upstream="refs/heads/main"/>'
'<project name="platform/vendor/y" path="vendor/y" '
'revision="52d3c9f7c107839ece2319d077de0cd922aa9d8f"/>'
'<superproject name="superproject"/>'
'</manifest>')
if __name__ == '__main__':
unittest.main()

View File

@ -42,7 +42,7 @@ class EventLogTestCase(unittest.TestCase):
self._event_log_module = git_trace2_event_log.EventLog(env=env)
self._log_data = None
def verifyCommonKeys(self, log_entry, expected_event_name, full_sid=True):
def verifyCommonKeys(self, log_entry, expected_event_name=None, full_sid=True):
"""Helper function to verify common event log keys."""
self.assertIn('event', log_entry)
self.assertIn('sid', log_entry)
@ -50,7 +50,8 @@ class EventLogTestCase(unittest.TestCase):
self.assertIn('time', log_entry)
# Do basic data format validation.
self.assertEqual(expected_event_name, log_entry['event'])
if expected_event_name:
self.assertEqual(expected_event_name, log_entry['event'])
if full_sid:
self.assertRegex(log_entry['sid'], self.FULL_SID_REGEX)
else:
@ -65,6 +66,13 @@ class EventLogTestCase(unittest.TestCase):
log_data.append(json.loads(line))
return log_data
def remove_prefix(self, s, prefix):
"""Return a copy string after removing |prefix| from |s|, if present or the original string."""
if s.startswith(prefix):
return s[len(prefix):]
else:
return s
def test_initial_state_with_parent_sid(self):
"""Test initial state when 'GIT_TRACE2_PARENT_SID' is set by parent."""
self.assertRegex(self._event_log_module.full_sid, self.FULL_SID_REGEX)
@ -234,6 +242,42 @@ class EventLogTestCase(unittest.TestCase):
self.assertEqual(len(self._log_data), 1)
self.verifyCommonKeys(self._log_data[0], expected_event_name='version')
def test_data_event_config(self):
"""Test 'data' event data outputs all config keys.
Expected event log:
<version event>
<data event>
<data event>
"""
config = {
'git.foo': 'bar',
'repo.partialclone': 'false',
'repo.syncstate.superproject.hassuperprojecttag': 'true',
'repo.syncstate.superproject.sys.argv': ['--', 'sync', 'protobuf'],
}
prefix_value = 'prefix'
self._event_log_module.LogDataConfigEvents(config, prefix_value)
with tempfile.TemporaryDirectory(prefix='event_log_tests') as tempdir:
log_path = self._event_log_module.Write(path=tempdir)
self._log_data = self.readLog(log_path)
self.assertEqual(len(self._log_data), 5)
data_events = self._log_data[1:]
self.verifyCommonKeys(self._log_data[0], expected_event_name='version')
for event in data_events:
self.verifyCommonKeys(event)
# Check for 'data' event specific fields.
self.assertIn('key', event)
self.assertIn('value', event)
key = event['key']
key = self.remove_prefix(key, f'{prefix_value}/')
value = event['value']
self.assertEqual(self._event_log_module.GetDataEventName(value), event['event'])
self.assertTrue(key in config and value == config[key])
def test_error_event(self):
"""Test and validate 'error' event data is valid.

View File

@ -261,6 +261,19 @@ class XmlManifestTests(ManifestParseTestCase):
<project name="repohooks" path="src/repohooks"/>
<repo-hooks in-project="repohooks" enabled-list="a, b"/>
</manifest>
""")
self.assertEqual(manifest.repo_hooks_project.name, 'repohooks')
self.assertEqual(manifest.repo_hooks_project.enabled_repo_hooks, ['a', 'b'])
def test_repo_hooks_unordered(self):
"""Check repo-hooks settings work even if the project def comes second."""
manifest = self.getXmlManifest("""
<manifest>
<remote name="test-remote" fetch="http://localhost" />
<default remote="test-remote" revision="refs/heads/main" />
<repo-hooks in-project="repohooks" enabled-list="a, b"/>
<project name="repohooks" path="src/repohooks"/>
</manifest>
""")
self.assertEqual(manifest.repo_hooks_project.name, 'repohooks')
self.assertEqual(manifest.repo_hooks_project.enabled_repo_hooks, ['a', 'b'])
@ -286,6 +299,25 @@ class XmlManifestTests(ManifestParseTestCase):
'<superproject name="superproject"/>'
'</manifest>')
def test_remote_annotations(self):
"""Check remote settings."""
manifest = self.getXmlManifest("""
<manifest>
<remote name="test-remote" fetch="http://localhost">
<annotation name="foo" value="bar"/>
</remote>
</manifest>
""")
self.assertEqual(manifest.remotes['test-remote'].annotations[0].name, 'foo')
self.assertEqual(manifest.remotes['test-remote'].annotations[0].value, 'bar')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="test-remote">'
'<annotation name="foo" value="bar"/>'
'</remote>'
'</manifest>')
class IncludeElementTests(ManifestParseTestCase):
"""Tests for <include>."""
@ -437,7 +469,7 @@ class ProjectElementTests(ManifestParseTestCase):
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="default-remote"/>'
'<default remote="default-remote" revision="refs/heads/main"/>'
'<project name="test-name" revision="ABCDEF"/>'
'<project name="test-name" revision="ABCDEF" upstream="refs/heads/main"/>'
'</manifest>')
def test_trailing_slash(self):
@ -540,6 +572,7 @@ class SuperProjectElementTests(ManifestParseTestCase):
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/superproject')
self.assertEqual(manifest.superproject['revision'], 'refs/heads/main')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
@ -548,6 +581,72 @@ class SuperProjectElementTests(ManifestParseTestCase):
'<superproject name="superproject"/>'
'</manifest>')
def test_superproject_revision(self):
"""Check superproject settings with a different revision attribute"""
self.maxDiff = None
manifest = self.getXmlManifest("""
<manifest>
<remote name="test-remote" fetch="http://localhost" />
<default remote="test-remote" revision="refs/heads/main" />
<superproject name="superproject" revision="refs/heads/stable" />
</manifest>
""")
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/superproject')
self.assertEqual(manifest.superproject['revision'], 'refs/heads/stable')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="test-remote"/>'
'<default remote="test-remote" revision="refs/heads/main"/>'
'<superproject name="superproject" revision="refs/heads/stable"/>'
'</manifest>')
def test_superproject_revision_default_negative(self):
"""Check superproject settings with a same revision attribute"""
self.maxDiff = None
manifest = self.getXmlManifest("""
<manifest>
<remote name="test-remote" fetch="http://localhost" />
<default remote="test-remote" revision="refs/heads/stable" />
<superproject name="superproject" revision="refs/heads/stable" />
</manifest>
""")
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/superproject')
self.assertEqual(manifest.superproject['revision'], 'refs/heads/stable')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="test-remote"/>'
'<default remote="test-remote" revision="refs/heads/stable"/>'
'<superproject name="superproject"/>'
'</manifest>')
def test_superproject_revision_remote(self):
"""Check superproject settings with a same revision attribute"""
self.maxDiff = None
manifest = self.getXmlManifest("""
<manifest>
<remote name="test-remote" fetch="http://localhost" revision="refs/heads/main" />
<default remote="test-remote" />
<superproject name="superproject" revision="refs/heads/stable" />
</manifest>
""")
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'test-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/superproject')
self.assertEqual(manifest.superproject['revision'], 'refs/heads/stable')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
'<remote fetch="http://localhost" name="test-remote" revision="refs/heads/main"/>'
'<default remote="test-remote"/>'
'<superproject name="superproject" revision="refs/heads/stable"/>'
'</manifest>')
def test_remote(self):
"""Check superproject settings with a remote."""
manifest = self.getXmlManifest("""
@ -561,6 +660,7 @@ class SuperProjectElementTests(ManifestParseTestCase):
self.assertEqual(manifest.superproject['name'], 'platform/superproject')
self.assertEqual(manifest.superproject['remote'].name, 'superproject-remote')
self.assertEqual(manifest.superproject['remote'].url, 'http://localhost/platform/superproject')
self.assertEqual(manifest.superproject['revision'], 'refs/heads/main')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
@ -581,6 +681,7 @@ class SuperProjectElementTests(ManifestParseTestCase):
""")
self.assertEqual(manifest.superproject['name'], 'superproject')
self.assertEqual(manifest.superproject['remote'].name, 'default-remote')
self.assertEqual(manifest.superproject['revision'], 'refs/heads/main')
self.assertEqual(
sort_attributes(manifest.ToXml().toxml()),
'<?xml version="1.0" ?><manifest>'
@ -632,9 +733,113 @@ class RemoteElementTests(ManifestParseTestCase):
def test_remote(self):
"""Check remote settings."""
a = manifest_xml._XmlRemote(name='foo')
b = manifest_xml._XmlRemote(name='bar')
a.AddAnnotation('key1', 'value1', 'true')
b = manifest_xml._XmlRemote(name='foo')
b.AddAnnotation('key2', 'value1', 'true')
c = manifest_xml._XmlRemote(name='foo')
c.AddAnnotation('key1', 'value2', 'true')
d = manifest_xml._XmlRemote(name='foo')
d.AddAnnotation('key1', 'value1', 'false')
self.assertEqual(a, a)
self.assertNotEqual(a, b)
self.assertNotEqual(a, c)
self.assertNotEqual(a, d)
self.assertNotEqual(a, manifest_xml._Default())
self.assertNotEqual(a, 123)
self.assertNotEqual(a, None)
class RemoveProjectElementTests(ManifestParseTestCase):
"""Tests for <remove-project>."""
def test_remove_one_project(self):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<project name="myproject" />
<remove-project name="myproject" />
</manifest>
""")
self.assertEqual(manifest.projects, [])
def test_remove_one_project_one_remains(self):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<project name="myproject" />
<project name="yourproject" />
<remove-project name="myproject" />
</manifest>
""")
self.assertEqual(len(manifest.projects), 1)
self.assertEqual(manifest.projects[0].name, 'yourproject')
def test_remove_one_project_doesnt_exist(self):
with self.assertRaises(manifest_xml.ManifestParseError):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<remove-project name="myproject" />
</manifest>
""")
manifest.projects
def test_remove_one_optional_project_doesnt_exist(self):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<remove-project name="myproject" optional="true" />
</manifest>
""")
self.assertEqual(manifest.projects, [])
class ExtendProjectElementTests(ManifestParseTestCase):
"""Tests for <extend-project>."""
def test_extend_project_dest_path_single_match(self):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<project name="myproject" />
<extend-project name="myproject" dest-path="bar" />
</manifest>
""")
self.assertEqual(len(manifest.projects), 1)
self.assertEqual(manifest.projects[0].relpath, 'bar')
def test_extend_project_dest_path_multi_match(self):
with self.assertRaises(manifest_xml.ManifestParseError):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<project name="myproject" path="x" />
<project name="myproject" path="y" />
<extend-project name="myproject" dest-path="bar" />
</manifest>
""")
manifest.projects
def test_extend_project_dest_path_multi_match_path_specified(self):
manifest = self.getXmlManifest("""
<manifest>
<remote name="default-remote" fetch="http://localhost" />
<default remote="default-remote" revision="refs/heads/main" />
<project name="myproject" path="x" />
<project name="myproject" path="y" />
<extend-project name="myproject" path="x" dest-path="bar" />
</manifest>
""")
self.assertEqual(len(manifest.projects), 2)
if manifest.projects[0].relpath == 'y':
self.assertEqual(manifest.projects[1].relpath, 'bar')
else:
self.assertEqual(manifest.projects[0].relpath, 'bar')
self.assertEqual(manifest.projects[1].relpath, 'y')

View File

@ -0,0 +1,50 @@
# Copyright 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unittests for the platform_utils.py module."""
import os
import tempfile
import unittest
import platform_utils
class RemoveTests(unittest.TestCase):
"""Check remove() helper."""
def testMissingOk(self):
"""Check missing_ok handling."""
with tempfile.TemporaryDirectory() as tmpdir:
path = os.path.join(tmpdir, 'test')
# Should not fail.
platform_utils.remove(path, missing_ok=True)
# Should fail.
self.assertRaises(OSError, platform_utils.remove, path)
self.assertRaises(OSError, platform_utils.remove, path, missing_ok=False)
# Should not fail if it exists.
open(path, 'w').close()
platform_utils.remove(path, missing_ok=True)
self.assertFalse(os.path.exists(path))
open(path, 'w').close()
platform_utils.remove(path)
self.assertFalse(os.path.exists(path))
open(path, 'w').close()
platform_utils.remove(path, missing_ok=False)
self.assertFalse(os.path.exists(path))