mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-06-30 20:17:08 +00:00
Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
5fb9c6a5b3 | |||
859d3d9580 | |||
fa8d939c8f | |||
a6c52f566a | |||
0d130d2da0 | |||
b750b48f50 | |||
6c8b894d8d | |||
b6cfa09500 | |||
78dcd3799b | |||
acc4c857a0 | |||
a39af3d432 | |||
4cdfdb7734 | |||
1eddca8476 | |||
aefa4d3a29 | |||
4ba29c42ca | |||
45ef9011c2 | |||
891e8f72ce | |||
af8fb132d5 | |||
4112c07688 | |||
fbd5dd3a30 | |||
3d27c71dd9 | |||
488d54d4ee | |||
5a5cfce1b2 | |||
e6d4b84060 | |||
d75ca2eb9d | |||
a010a9f4a0 | |||
8a54a7eac3 | |||
63a5657ecf | |||
07d21e6bde | |||
076d54652e | |||
790f4cea7a | |||
39cb17f7a3 | |||
ad1b7bd2e2 | |||
3c2d807905 | |||
7fa8eedd8f | |||
dede564c3d | |||
ac76fd3e3a | |||
a8c34d1075 | |||
5951e3043f | |||
48ea25c6a7 | |||
355f4398d8 | |||
bddc964d93 | |||
a8cf575d68 | |||
8501d4602a | |||
8db78c7d4d | |||
9fb64ae29c | |||
d47d9ff1cb | |||
68d69635c7 | |||
ff6b1dae1e | |||
bdcba7dc36 | |||
1d00a7e2ae | |||
3a0a145b0e | |||
74737da1ab | |||
0ddb677611 | |||
501733c2ab | |||
0165e20fcc | |||
0de4fc3001 | |||
4c11aebeb9 | |||
b90a422ab6 | |||
a46047a822 | |||
5fa912b0d1 | |||
4ada043dc0 | |||
d8de29c447 | |||
2cc3ab7663 |
23
command.py
23
command.py
@ -144,11 +144,10 @@ class Command(object):
|
|||||||
help=f'number of jobs to run in parallel (default: {default})')
|
help=f'number of jobs to run in parallel (default: {default})')
|
||||||
|
|
||||||
m = p.add_option_group('Multi-manifest options')
|
m = p.add_option_group('Multi-manifest options')
|
||||||
m.add_option('--outer-manifest', action='store_true',
|
m.add_option('--outer-manifest', action='store_true', default=None,
|
||||||
help='operate starting at the outermost manifest')
|
help='operate starting at the outermost manifest')
|
||||||
m.add_option('--no-outer-manifest', dest='outer_manifest',
|
m.add_option('--no-outer-manifest', dest='outer_manifest',
|
||||||
action='store_false', default=None,
|
action='store_false', help='do not operate on outer manifests')
|
||||||
help='do not operate on outer manifests')
|
|
||||||
m.add_option('--this-manifest-only', action='store_true', default=None,
|
m.add_option('--this-manifest-only', action='store_true', default=None,
|
||||||
help='only operate on this (sub)manifest')
|
help='only operate on this (sub)manifest')
|
||||||
m.add_option('--no-this-manifest-only', '--all-manifests',
|
m.add_option('--no-this-manifest-only', '--all-manifests',
|
||||||
@ -186,6 +185,10 @@ class Command(object):
|
|||||||
"""Validate common options."""
|
"""Validate common options."""
|
||||||
opt.quiet = opt.output_mode is False
|
opt.quiet = opt.output_mode is False
|
||||||
opt.verbose = opt.output_mode is True
|
opt.verbose = opt.output_mode is True
|
||||||
|
if opt.outer_manifest is None:
|
||||||
|
# By default, treat multi-manifest instances as a single manifest from
|
||||||
|
# the user's perspective.
|
||||||
|
opt.outer_manifest = True
|
||||||
|
|
||||||
def ValidateOptions(self, opt, args):
|
def ValidateOptions(self, opt, args):
|
||||||
"""Validate the user options & arguments before executing.
|
"""Validate the user options & arguments before executing.
|
||||||
@ -274,6 +277,18 @@ class Command(object):
|
|||||||
def GetProjects(self, args, manifest=None, groups='', missing_ok=False,
|
def GetProjects(self, args, manifest=None, groups='', missing_ok=False,
|
||||||
submodules_ok=False, all_manifests=False):
|
submodules_ok=False, all_manifests=False):
|
||||||
"""A list of projects that match the arguments.
|
"""A list of projects that match the arguments.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: a list of (case-insensitive) strings, projects to search for.
|
||||||
|
manifest: an XmlManifest, the manifest to use, or None for default.
|
||||||
|
groups: a string, the manifest groups in use.
|
||||||
|
missing_ok: a boolean, whether to allow missing projects.
|
||||||
|
submodules_ok: a boolean, whether to allow submodules.
|
||||||
|
all_manifests: a boolean, if True then all manifests and submanifests are
|
||||||
|
used. If False, then only the local (sub)manifest is used.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of matching Project instances.
|
||||||
"""
|
"""
|
||||||
if all_manifests:
|
if all_manifests:
|
||||||
if not manifest:
|
if not manifest:
|
||||||
@ -385,7 +400,7 @@ class Command(object):
|
|||||||
opt: The command options.
|
opt: The command options.
|
||||||
"""
|
"""
|
||||||
top = self.outer_manifest
|
top = self.outer_manifest
|
||||||
if opt.outer_manifest is False or opt.this_manifest_only:
|
if not opt.outer_manifest or opt.this_manifest_only:
|
||||||
top = self.manifest
|
top = self.manifest
|
||||||
yield top
|
yield top
|
||||||
if not opt.this_manifest_only:
|
if not opt.this_manifest_only:
|
||||||
|
@ -66,6 +66,7 @@ following DTD:
|
|||||||
<!ATTLIST submanifest revision CDATA #IMPLIED>
|
<!ATTLIST submanifest revision CDATA #IMPLIED>
|
||||||
<!ATTLIST submanifest path CDATA #IMPLIED>
|
<!ATTLIST submanifest path CDATA #IMPLIED>
|
||||||
<!ATTLIST submanifest groups CDATA #IMPLIED>
|
<!ATTLIST submanifest groups CDATA #IMPLIED>
|
||||||
|
<!ATTLIST submanifest default-groups CDATA #IMPLIED>
|
||||||
|
|
||||||
<!ELEMENT project (annotation*,
|
<!ELEMENT project (annotation*,
|
||||||
project*,
|
project*,
|
||||||
@ -104,6 +105,8 @@ following DTD:
|
|||||||
<!ATTLIST extend-project groups CDATA #IMPLIED>
|
<!ATTLIST extend-project groups CDATA #IMPLIED>
|
||||||
<!ATTLIST extend-project revision CDATA #IMPLIED>
|
<!ATTLIST extend-project revision CDATA #IMPLIED>
|
||||||
<!ATTLIST extend-project remote CDATA #IMPLIED>
|
<!ATTLIST extend-project remote CDATA #IMPLIED>
|
||||||
|
<!ATTLIST extend-project dest-branch CDATA #IMPLIED>
|
||||||
|
<!ATTLIST extend-project upstream CDATA #IMPLIED>
|
||||||
|
|
||||||
<!ELEMENT remove-project EMPTY>
|
<!ELEMENT remove-project EMPTY>
|
||||||
<!ATTLIST remove-project name CDATA #REQUIRED>
|
<!ATTLIST remove-project name CDATA #REQUIRED>
|
||||||
@ -302,6 +305,9 @@ in the included submanifest belong. This appends and recurses, meaning
|
|||||||
all projects in submanifests carry all parent submanifest groups.
|
all projects in submanifests carry all parent submanifest groups.
|
||||||
Same syntax as the corresponding element of `project`.
|
Same syntax as the corresponding element of `project`.
|
||||||
|
|
||||||
|
Attribute `default-groups`: The list of manifest groups to sync if no
|
||||||
|
`--groups=` parameter was specified at init. When that list is empty, use this
|
||||||
|
list instead of "default" as the list of groups to sync.
|
||||||
|
|
||||||
### Element project
|
### Element project
|
||||||
|
|
||||||
@ -419,6 +425,12 @@ project. Same syntax as the corresponding element of `project`.
|
|||||||
Attribute `remote`: If specified, overrides the remote of the original
|
Attribute `remote`: If specified, overrides the remote of the original
|
||||||
project. Same syntax as the corresponding element of `project`.
|
project. Same syntax as the corresponding element of `project`.
|
||||||
|
|
||||||
|
Attribute `dest-branch`: If specified, overrides the dest-branch of the original
|
||||||
|
project. Same syntax as the corresponding element of `project`.
|
||||||
|
|
||||||
|
Attribute `upstream`: If specified, overrides the upstream of the original
|
||||||
|
project. Same syntax as the corresponding element of `project`.
|
||||||
|
|
||||||
### Element annotation
|
### Element annotation
|
||||||
|
|
||||||
Zero or more annotation elements may be specified as children of a
|
Zero or more annotation elements may be specified as children of a
|
||||||
|
@ -158,6 +158,8 @@ def git_require(min_version, fail=False, msg=''):
|
|||||||
|
|
||||||
|
|
||||||
class GitCommand(object):
|
class GitCommand(object):
|
||||||
|
"""Wrapper around a single git invocation."""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
project,
|
project,
|
||||||
cmdv,
|
cmdv,
|
||||||
@ -279,14 +281,9 @@ class GitCommand(object):
|
|||||||
ssh_proxy.add_client(p)
|
ssh_proxy.add_client(p)
|
||||||
|
|
||||||
self.process = p
|
self.process = p
|
||||||
if input:
|
|
||||||
if isinstance(input, str):
|
|
||||||
input = input.encode('utf-8')
|
|
||||||
p.stdin.write(input)
|
|
||||||
p.stdin.close()
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.stdout, self.stderr = p.communicate()
|
self.stdout, self.stderr = p.communicate(input=input)
|
||||||
finally:
|
finally:
|
||||||
if ssh_proxy:
|
if ssh_proxy:
|
||||||
ssh_proxy.remove_client(p)
|
ssh_proxy.remove_client(p)
|
||||||
|
@ -18,7 +18,7 @@ For more information on superproject, check out:
|
|||||||
https://en.wikibooks.org/wiki/Git/Submodules_and_Superprojects
|
https://en.wikibooks.org/wiki/Git/Submodules_and_Superprojects
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
superproject = Superproject()
|
superproject = Superproject(manifest, name, remote, revision)
|
||||||
UpdateProjectsResult = superproject.UpdateProjectsRevisionId(projects)
|
UpdateProjectsResult = superproject.UpdateProjectsRevisionId(projects)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -99,8 +99,8 @@ class Superproject(object):
|
|||||||
self._work_git_name = git_name + _SUPERPROJECT_GIT_NAME
|
self._work_git_name = git_name + _SUPERPROJECT_GIT_NAME
|
||||||
self._work_git = os.path.join(self._superproject_path, self._work_git_name)
|
self._work_git = os.path.join(self._superproject_path, self._work_git_name)
|
||||||
|
|
||||||
# The following are command arguemnts, rather then superproject attributes,
|
# The following are command arguemnts, rather than superproject attributes,
|
||||||
# and where included here originally. They should eventually become
|
# and were included here originally. They should eventually become
|
||||||
# arguments that are passed down from the public methods, instead of being
|
# arguments that are passed down from the public methods, instead of being
|
||||||
# treated as attributes.
|
# treated as attributes.
|
||||||
self._git_event_log = None
|
self._git_event_log = None
|
||||||
@ -238,8 +238,8 @@ class Superproject(object):
|
|||||||
f'{self._manifest.manifestFile}')
|
f'{self._manifest.manifestFile}')
|
||||||
return SyncResult(False, False)
|
return SyncResult(False, False)
|
||||||
|
|
||||||
print('NOTICE: --use-superproject is in beta; report any issues to the '
|
_PrintBetaNotice()
|
||||||
'address described in `repo version`', file=sys.stderr)
|
|
||||||
should_exit = True
|
should_exit = True
|
||||||
if not self._remote_url:
|
if not self._remote_url:
|
||||||
self._LogWarning(f'superproject URL is not defined in manifest: '
|
self._LogWarning(f'superproject URL is not defined in manifest: '
|
||||||
@ -295,7 +295,8 @@ class Superproject(object):
|
|||||||
if not os.path.exists(self._superproject_path):
|
if not os.path.exists(self._superproject_path):
|
||||||
self._LogWarning(f'missing superproject directory: {self._superproject_path}')
|
self._LogWarning(f'missing superproject directory: {self._superproject_path}')
|
||||||
return None
|
return None
|
||||||
manifest_str = self._manifest.ToXml(groups=self._manifest.GetGroupsStr()).toxml()
|
manifest_str = self._manifest.ToXml(groups=self._manifest.GetGroupsStr(),
|
||||||
|
omit_local=True).toxml()
|
||||||
manifest_path = self._manifest_path
|
manifest_path = self._manifest_path
|
||||||
try:
|
try:
|
||||||
with open(manifest_path, 'w', encoding='utf-8') as fp:
|
with open(manifest_path, 'w', encoding='utf-8') as fp:
|
||||||
@ -329,7 +330,8 @@ class Superproject(object):
|
|||||||
"""Update revisionId of every project in projects with the commit id.
|
"""Update revisionId of every project in projects with the commit id.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
projects: List of projects whose revisionId needs to be updated.
|
projects: a list of projects whose revisionId needs to be updated.
|
||||||
|
git_event_log: an EventLog, for git tracing.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
UpdateProjectsResult
|
UpdateProjectsResult
|
||||||
@ -364,6 +366,13 @@ class Superproject(object):
|
|||||||
return UpdateProjectsResult(manifest_path, False)
|
return UpdateProjectsResult(manifest_path, False)
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache(maxsize=10)
|
||||||
|
def _PrintBetaNotice():
|
||||||
|
"""Print the notice of beta status."""
|
||||||
|
print('NOTICE: --use-superproject is in beta; report any issues to the '
|
||||||
|
'address described in `repo version`', file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache(maxsize=None)
|
@functools.lru_cache(maxsize=None)
|
||||||
def _UseSuperprojectFromConfiguration():
|
def _UseSuperprojectFromConfiguration():
|
||||||
"""Returns the user choice of whether to use superproject."""
|
"""Returns the user choice of whether to use superproject."""
|
||||||
@ -408,16 +417,32 @@ def _UseSuperprojectFromConfiguration():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def PrintMessages(opt, manifest):
|
def PrintMessages(use_superproject, manifest):
|
||||||
"""Returns a boolean if error/warning messages are to be printed."""
|
"""Returns a boolean if error/warning messages are to be printed.
|
||||||
return opt.use_superproject is not None or bool(manifest.superproject)
|
|
||||||
|
Args:
|
||||||
|
use_superproject: option value from optparse.
|
||||||
|
manifest: manifest to use.
|
||||||
|
"""
|
||||||
|
return use_superproject is not None or bool(manifest.superproject)
|
||||||
|
|
||||||
|
|
||||||
def UseSuperproject(opt, manifest):
|
def UseSuperproject(use_superproject, manifest):
|
||||||
"""Returns a boolean if use-superproject option is enabled."""
|
"""Returns a boolean if use-superproject option is enabled.
|
||||||
|
|
||||||
if opt.use_superproject is not None:
|
Args:
|
||||||
return opt.use_superproject
|
use_superproject: option value from optparse.
|
||||||
|
manifest: manifest to use.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Whether the superproject should be used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not manifest.superproject:
|
||||||
|
# This (sub) manifest does not have a superproject definition.
|
||||||
|
return False
|
||||||
|
elif use_superproject is not None:
|
||||||
|
return use_superproject
|
||||||
else:
|
else:
|
||||||
client_value = manifest.manifestProject.use_superproject
|
client_value = manifest.manifestProject.use_superproject
|
||||||
if client_value is not None:
|
if client_value is not None:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# From Gerrit Code Review 3.1.3
|
# From Gerrit Code Review 3.6.1 c67916dbdc07555c44e32a68f92ffc484b9b34f0
|
||||||
#
|
#
|
||||||
# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
|
# Part of Gerrit Code Review (https://www.gerritcodereview.com/)
|
||||||
#
|
#
|
||||||
@ -17,6 +17,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
# avoid [[ which is not POSIX sh.
|
# avoid [[ which is not POSIX sh.
|
||||||
if test "$#" != 1 ; then
|
if test "$#" != 1 ; then
|
||||||
echo "$0 requires an argument."
|
echo "$0 requires an argument."
|
||||||
@ -29,15 +31,25 @@ if test ! -f "$1" ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Do not create a change id if requested
|
# Do not create a change id if requested
|
||||||
if test "false" = "`git config --bool --get gerrit.createChangeId`" ; then
|
if test "false" = "$(git config --bool --get gerrit.createChangeId)" ; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# $RANDOM will be undefined if not using bash, so don't use set -u
|
# Do not create a change id for squash commits.
|
||||||
random=$( (whoami ; hostname ; date; cat $1 ; echo $RANDOM) | git hash-object --stdin)
|
if head -n1 "$1" | grep -q '^squash! '; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git rev-parse --verify HEAD >/dev/null 2>&1; then
|
||||||
|
refhash="$(git rev-parse HEAD)"
|
||||||
|
else
|
||||||
|
refhash="$(git hash-object -t tree /dev/null)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
random=$({ git var GIT_COMMITTER_IDENT ; echo "$refhash" ; cat "$1"; } | git hash-object --stdin)
|
||||||
dest="$1.tmp.${random}"
|
dest="$1.tmp.${random}"
|
||||||
|
|
||||||
trap 'rm -f "${dest}"' EXIT
|
trap 'rm -f "$dest" "$dest-2"' EXIT
|
||||||
|
|
||||||
if ! git stripspace --strip-comments < "$1" > "${dest}" ; then
|
if ! git stripspace --strip-comments < "$1" > "${dest}" ; then
|
||||||
echo "cannot strip comments from $1"
|
echo "cannot strip comments from $1"
|
||||||
@ -49,11 +61,40 @@ if test ! -s "${dest}" ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
reviewurl="$(git config --get gerrit.reviewUrl)"
|
||||||
|
if test -n "${reviewurl}" ; then
|
||||||
|
token="Link"
|
||||||
|
value="${reviewurl%/}/id/I$random"
|
||||||
|
pattern=".*/id/I[0-9a-f]\{40\}$"
|
||||||
|
else
|
||||||
|
token="Change-Id"
|
||||||
|
value="I$random"
|
||||||
|
pattern=".*"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if git interpret-trailers --parse < "$1" | grep -q "^$token: $pattern$" ; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# There must be a Signed-off-by trailer for the code below to work. Insert a
|
||||||
|
# sentinel at the end to make sure there is one.
|
||||||
# Avoid the --in-place option which only appeared in Git 2.8
|
# Avoid the --in-place option which only appeared in Git 2.8
|
||||||
# Avoid the --if-exists option which only appeared in Git 2.15
|
if ! git interpret-trailers \
|
||||||
if ! git -c trailer.ifexists=doNothing interpret-trailers \
|
--trailer "Signed-off-by: SENTINEL" < "$1" > "$dest-2" ; then
|
||||||
--trailer "Change-Id: I${random}" < "$1" > "${dest}" ; then
|
echo "cannot insert Signed-off-by sentinel line in $1"
|
||||||
echo "cannot insert change-id line in $1"
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure the trailer appears before any Signed-off-by trailers by inserting
|
||||||
|
# it as if it was a Signed-off-by trailer and then use sed to remove the
|
||||||
|
# Signed-off-by prefix and the Signed-off-by sentinel line.
|
||||||
|
# Avoid the --in-place option which only appeared in Git 2.8
|
||||||
|
# Avoid the --where option which only appeared in Git 2.15
|
||||||
|
if ! git -c trailer.where=before interpret-trailers \
|
||||||
|
--trailer "Signed-off-by: $token: $value" < "$dest-2" |
|
||||||
|
sed -re "s/^Signed-off-by: ($token: )/\1/" \
|
||||||
|
-e "/^Signed-off-by: SENTINEL/d" > "$dest" ; then
|
||||||
|
echo "cannot insert $token line in $1"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
5
main.py
5
main.py
@ -294,8 +294,7 @@ class _Repo(object):
|
|||||||
cmd.ValidateOptions(copts, cargs)
|
cmd.ValidateOptions(copts, cargs)
|
||||||
|
|
||||||
this_manifest_only = copts.this_manifest_only
|
this_manifest_only = copts.this_manifest_only
|
||||||
# If not specified, default to using the outer manifest.
|
outer_manifest = copts.outer_manifest
|
||||||
outer_manifest = copts.outer_manifest is not False
|
|
||||||
if cmd.MULTI_MANIFEST_SUPPORT or this_manifest_only:
|
if cmd.MULTI_MANIFEST_SUPPORT or this_manifest_only:
|
||||||
result = cmd.Execute(copts, cargs)
|
result = cmd.Execute(copts, cargs)
|
||||||
elif outer_manifest and repo_client.manifest.is_submanifest:
|
elif outer_manifest and repo_client.manifest.is_submanifest:
|
||||||
@ -310,7 +309,7 @@ class _Repo(object):
|
|||||||
# (sub)manifest, and then any child submanifests.
|
# (sub)manifest, and then any child submanifests.
|
||||||
result = cmd.Execute(copts, cargs)
|
result = cmd.Execute(copts, cargs)
|
||||||
for submanifest in repo_client.manifest.submanifests.values():
|
for submanifest in repo_client.manifest.submanifests.values():
|
||||||
spec = submanifest.ToSubmanifestSpec(root=repo_client.outer_client)
|
spec = submanifest.ToSubmanifestSpec()
|
||||||
gopts.submanifest_path = submanifest.repo_client.path_prefix
|
gopts.submanifest_path = submanifest.repo_client.path_prefix
|
||||||
child_argv = argv[:]
|
child_argv = argv[:]
|
||||||
child_argv.append('--no-outer-manifest')
|
child_argv.append('--no-outer-manifest')
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo abandon" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo abandon" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo abandon - manual page for repo abandon
|
repo \- repo abandon - manual page for repo abandon
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -32,5 +32,18 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help abandon` to view the detailed manual.
|
Run `repo help abandon` to view the detailed manual.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo branches" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo branches" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo branches - manual page for repo branches
|
repo \- repo branches - manual page for repo branches
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -55,5 +55,18 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help branches` to view the detailed manual.
|
Run `repo help branches` to view the detailed manual.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo checkout" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo checkout" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo checkout - manual page for repo checkout
|
repo \- repo checkout - manual page for repo checkout
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -24,6 +24,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help checkout` to view the detailed manual.
|
Run `repo help checkout` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo cherry-pick" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo cherry-pick" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo cherry-pick - manual page for repo cherry-pick
|
repo \- repo cherry-pick - manual page for repo cherry-pick
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -20,6 +20,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help cherry\-pick` to view the detailed manual.
|
Run `repo help cherry\-pick` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo diff" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo diff" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo diff - manual page for repo diff
|
repo \- repo diff - manual page for repo diff
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -31,5 +31,18 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help diff` to view the detailed manual.
|
Run `repo help diff` to view the detailed manual.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo diffmanifests" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo diffmanifests" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo diffmanifests - manual page for repo diffmanifests
|
repo \- repo diffmanifests - manual page for repo diffmanifests
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -29,6 +29,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help diffmanifests` to view the detailed manual.
|
Run `repo help diffmanifests` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo download" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo download" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo download - manual page for repo download
|
repo \- repo download - manual page for repo download
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -35,6 +35,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help download` to view the detailed manual.
|
Run `repo help download` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo forall" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo forall" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo forall - manual page for repo forall
|
repo \- repo forall - manual page for repo forall
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -54,6 +54,19 @@ only show errors
|
|||||||
.TP
|
.TP
|
||||||
\fB\-p\fR
|
\fB\-p\fR
|
||||||
show project headers before output
|
show project headers before output
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help forall` to view the detailed manual.
|
Run `repo help forall` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
@ -93,6 +106,11 @@ REPO_PROJECT is set to the unique name of the project.
|
|||||||
.PP
|
.PP
|
||||||
REPO_PATH is the path relative the the root of the client.
|
REPO_PATH is the path relative the the root of the client.
|
||||||
.PP
|
.PP
|
||||||
|
REPO_OUTERPATH is the path of the sub manifest's root relative to the root of
|
||||||
|
the client.
|
||||||
|
.PP
|
||||||
|
REPO_INNERPATH is the path relative to the root of the sub manifest.
|
||||||
|
.PP
|
||||||
REPO_REMOTE is the name of the remote system from the manifest.
|
REPO_REMOTE is the name of the remote system from the manifest.
|
||||||
.PP
|
.PP
|
||||||
REPO_LREV is the name of the revision from the manifest, translated to a local
|
REPO_LREV is the name of the revision from the manifest, translated to a local
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo gitc-delete" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo gitc-delete" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo gitc-delete - manual page for repo gitc-delete
|
repo \- repo gitc-delete - manual page for repo gitc-delete
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -23,6 +23,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help gitc\-delete` to view the detailed manual.
|
Run `repo help gitc\-delete` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "November 2021" "repo gitc-init" "Repo Manual"
|
.TH REPO "1" "October 2022" "repo gitc-init" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo gitc-init - manual page for repo gitc-init
|
repo \- repo gitc-init - manual page for repo gitc-init
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -45,10 +45,15 @@ sync any submodules associated with the manifest repo
|
|||||||
\fB\-\-standalone\-manifest\fR
|
\fB\-\-standalone\-manifest\fR
|
||||||
download the manifest as a static file rather then
|
download the manifest as a static file rather then
|
||||||
create a git checkout of the manifest repo
|
create a git checkout of the manifest repo
|
||||||
|
.TP
|
||||||
|
\fB\-\-manifest\-depth\fR=\fI\,DEPTH\/\fR
|
||||||
|
create a shallow clone of the manifest repo with given
|
||||||
|
depth (0 for full clone); see git clone (default: 0)
|
||||||
.SS Manifest (only) checkout options:
|
.SS Manifest (only) checkout options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-current\-branch\fR
|
\fB\-\-current\-branch\fR
|
||||||
fetch only current manifest branch from server
|
fetch only current manifest branch from server
|
||||||
|
(default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-current\-branch\fR
|
\fB\-\-no\-current\-branch\fR
|
||||||
fetch all manifest branches from server
|
fetch all manifest branches from server
|
||||||
@ -109,6 +114,12 @@ not \fB\-\-partial\-clone\fR)
|
|||||||
\fB\-\-no\-clone\-bundle\fR
|
\fB\-\-no\-clone\-bundle\fR
|
||||||
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
|
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
|
||||||
\fB\-\-partial\-clone\fR)
|
\fB\-\-partial\-clone\fR)
|
||||||
|
.TP
|
||||||
|
\fB\-\-git\-lfs\fR
|
||||||
|
enable Git LFS support
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-git\-lfs\fR
|
||||||
|
disable Git LFS support
|
||||||
.SS repo Version options:
|
.SS repo Version options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-repo\-url\fR=\fI\,URL\/\fR
|
\fB\-\-repo\-url\fR=\fI\,URL\/\fR
|
||||||
@ -130,6 +141,19 @@ Optional manifest file to use for this GITC client.
|
|||||||
.TP
|
.TP
|
||||||
\fB\-c\fR GITC_CLIENT, \fB\-\-gitc\-client\fR=\fI\,GITC_CLIENT\/\fR
|
\fB\-c\fR GITC_CLIENT, \fB\-\-gitc\-client\fR=\fI\,GITC_CLIENT\/\fR
|
||||||
Name of the gitc_client instance to create or modify.
|
Name of the gitc_client instance to create or modify.
|
||||||
|
.SS Multi\-manifest:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help gitc\-init` to view the detailed manual.
|
Run `repo help gitc\-init` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo grep" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo grep" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo grep - manual page for repo grep
|
repo \- repo grep - manual page for repo grep
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -24,6 +24,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.SS Sources:
|
.SS Sources:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-cached\fR
|
\fB\-\-cached\fR
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo help" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo help" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo help - manual page for repo help
|
repo \- repo help - manual page for repo help
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -26,6 +26,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help help` to view the detailed manual.
|
Run `repo help help` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo info" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo info" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo info - manual page for repo info
|
repo \- repo info - manual page for repo info
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -36,5 +36,18 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help info` to view the detailed manual.
|
Run `repo help info` to view the detailed manual.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "November 2021" "repo init" "Repo Manual"
|
.TH REPO "1" "October 2022" "repo init" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo init - manual page for repo init
|
repo \- repo init - manual page for repo init
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -45,10 +45,15 @@ sync any submodules associated with the manifest repo
|
|||||||
\fB\-\-standalone\-manifest\fR
|
\fB\-\-standalone\-manifest\fR
|
||||||
download the manifest as a static file rather then
|
download the manifest as a static file rather then
|
||||||
create a git checkout of the manifest repo
|
create a git checkout of the manifest repo
|
||||||
|
.TP
|
||||||
|
\fB\-\-manifest\-depth\fR=\fI\,DEPTH\/\fR
|
||||||
|
create a shallow clone of the manifest repo with given
|
||||||
|
depth (0 for full clone); see git clone (default: 0)
|
||||||
.SS Manifest (only) checkout options:
|
.SS Manifest (only) checkout options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-c\fR, \fB\-\-current\-branch\fR
|
\fB\-c\fR, \fB\-\-current\-branch\fR
|
||||||
fetch only current manifest branch from server
|
fetch only current manifest branch from server
|
||||||
|
(default)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-current\-branch\fR
|
\fB\-\-no\-current\-branch\fR
|
||||||
fetch all manifest branches from server
|
fetch all manifest branches from server
|
||||||
@ -109,6 +114,12 @@ not \fB\-\-partial\-clone\fR)
|
|||||||
\fB\-\-no\-clone\-bundle\fR
|
\fB\-\-no\-clone\-bundle\fR
|
||||||
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
|
disable use of \fI\,/clone.bundle\/\fP on HTTP/HTTPS (default if
|
||||||
\fB\-\-partial\-clone\fR)
|
\fB\-\-partial\-clone\fR)
|
||||||
|
.TP
|
||||||
|
\fB\-\-git\-lfs\fR
|
||||||
|
enable Git LFS support
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-git\-lfs\fR
|
||||||
|
disable Git LFS support
|
||||||
.SS repo Version options:
|
.SS repo Version options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-repo\-url\fR=\fI\,URL\/\fR
|
\fB\-\-repo\-url\fR=\fI\,URL\/\fR
|
||||||
@ -123,6 +134,19 @@ do not verify repo source code
|
|||||||
.TP
|
.TP
|
||||||
\fB\-\-config\-name\fR
|
\fB\-\-config\-name\fR
|
||||||
Always prompt for name/e\-mail
|
Always prompt for name/e\-mail
|
||||||
|
.SS Multi\-manifest:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help init` to view the detailed manual.
|
Run `repo help init` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo list" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo list" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo list - manual page for repo list
|
repo \- repo list - manual page for repo list
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -47,6 +47,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help list` to view the detailed manual.
|
Run `repo help list` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "November 2021" "repo manifest" "Repo Manual"
|
.TH REPO "1" "October 2022" "repo manifest" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo manifest - manual page for repo manifest
|
repo \- repo manifest - manual page for repo manifest
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -40,7 +40,8 @@ format output for humans to read
|
|||||||
ignore local manifests
|
ignore local manifests
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR \-|NAME.xml, \fB\-\-output\-file\fR=\fI\,\-\/\fR|NAME.xml
|
\fB\-o\fR \-|NAME.xml, \fB\-\-output\-file\fR=\fI\,\-\/\fR|NAME.xml
|
||||||
file to save the manifest to
|
file to save the manifest to. (Filename prefix for
|
||||||
|
multi\-tree.)
|
||||||
.SS Logging options:
|
.SS Logging options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-v\fR, \fB\-\-verbose\fR
|
\fB\-v\fR, \fB\-\-verbose\fR
|
||||||
@ -48,6 +49,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help manifest` to view the detailed manual.
|
Run `repo help manifest` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
@ -88,6 +102,7 @@ A manifest XML file (e.g. `default.xml`) roughly conforms to the following DTD:
|
|||||||
remote*,
|
remote*,
|
||||||
default?,
|
default?,
|
||||||
manifest\-server?,
|
manifest\-server?,
|
||||||
|
submanifest*?,
|
||||||
remove\-project*,
|
remove\-project*,
|
||||||
project*,
|
project*,
|
||||||
extend\-project*,
|
extend\-project*,
|
||||||
@ -118,6 +133,16 @@ include*)>
|
|||||||
.IP
|
.IP
|
||||||
<!ELEMENT manifest\-server EMPTY>
|
<!ELEMENT manifest\-server EMPTY>
|
||||||
<!ATTLIST manifest\-server url CDATA #REQUIRED>
|
<!ATTLIST manifest\-server url CDATA #REQUIRED>
|
||||||
|
.IP
|
||||||
|
<!ELEMENT submanifest EMPTY>
|
||||||
|
<!ATTLIST submanifest name ID #REQUIRED>
|
||||||
|
<!ATTLIST submanifest remote IDREF #IMPLIED>
|
||||||
|
<!ATTLIST submanifest project CDATA #IMPLIED>
|
||||||
|
<!ATTLIST submanifest manifest\-name CDATA #IMPLIED>
|
||||||
|
<!ATTLIST submanifest revision CDATA #IMPLIED>
|
||||||
|
<!ATTLIST submanifest path CDATA #IMPLIED>
|
||||||
|
<!ATTLIST submanifest groups CDATA #IMPLIED>
|
||||||
|
<!ATTLIST submanifest default\-groups CDATA #IMPLIED>
|
||||||
.TP
|
.TP
|
||||||
<!ELEMENT project (annotation*,
|
<!ELEMENT project (annotation*,
|
||||||
project*,
|
project*,
|
||||||
@ -165,6 +190,8 @@ CDATA #IMPLIED>
|
|||||||
<!ATTLIST extend\-project groups CDATA #IMPLIED>
|
<!ATTLIST extend\-project groups CDATA #IMPLIED>
|
||||||
<!ATTLIST extend\-project revision CDATA #IMPLIED>
|
<!ATTLIST extend\-project revision CDATA #IMPLIED>
|
||||||
<!ATTLIST extend\-project remote CDATA #IMPLIED>
|
<!ATTLIST extend\-project remote CDATA #IMPLIED>
|
||||||
|
<!ATTLIST extend\-project dest\-branch CDATA #IMPLIED>
|
||||||
|
<!ATTLIST extend\-project upstream CDATA #IMPLIED>
|
||||||
.IP
|
.IP
|
||||||
<!ELEMENT remove\-project EMPTY>
|
<!ELEMENT remove\-project EMPTY>
|
||||||
<!ATTLIST remove\-project name CDATA #REQUIRED>
|
<!ATTLIST remove\-project name CDATA #REQUIRED>
|
||||||
@ -295,6 +322,65 @@ GetManifest(tag)
|
|||||||
Return a manifest in which each project is pegged to the revision at the
|
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.
|
specified tag. This is used by repo sync when the \fB\-\-smart\-tag\fR option is given.
|
||||||
.PP
|
.PP
|
||||||
|
Element submanifest
|
||||||
|
.PP
|
||||||
|
One or more submanifest elements may be specified. Each element describes a
|
||||||
|
single manifest to be checked out as a child.
|
||||||
|
.PP
|
||||||
|
Attribute `name`: A unique name (within the current (sub)manifest) for this
|
||||||
|
submanifest. It acts as a default for `revision` below. The same name can be
|
||||||
|
used for submanifests with different parent (sub)manifests.
|
||||||
|
.PP
|
||||||
|
Attribute `remote`: Name of a previously defined remote element. If not supplied
|
||||||
|
the remote given by the default element is used.
|
||||||
|
.PP
|
||||||
|
Attribute `project`: The manifest project name. 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
|
||||||
|
`project` 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.
|
||||||
|
.PP
|
||||||
|
If not supplied the remote and project for this manifest will be used: `remote`
|
||||||
|
cannot be supplied.
|
||||||
|
.PP
|
||||||
|
Projects from a submanifest and its submanifests are added to the
|
||||||
|
submanifest::path:<path_prefix> group.
|
||||||
|
.PP
|
||||||
|
Attribute `manifest\-name`: The manifest filename in the manifest project. If not
|
||||||
|
supplied, `default.xml` is used.
|
||||||
|
.PP
|
||||||
|
Attribute `revision`: Name of a Git branch (e.g. "main" or "refs/heads/main"),
|
||||||
|
tag (e.g. "refs/tags/stable"), or a commit hash. If not supplied, `name` is
|
||||||
|
used.
|
||||||
|
.PP
|
||||||
|
Attribute `path`: An optional path relative to the top directory of the repo
|
||||||
|
client where the submanifest repo client top directory should be placed. If not
|
||||||
|
supplied, `revision` is used.
|
||||||
|
.PP
|
||||||
|
`path` may not be an absolute path or use "." or ".." path components.
|
||||||
|
.PP
|
||||||
|
Attribute `groups`: List of additional groups to which all projects in the
|
||||||
|
included submanifest belong. This appends and recurses, meaning all projects in
|
||||||
|
submanifests carry all parent submanifest groups. Same syntax as the
|
||||||
|
corresponding element of `project`.
|
||||||
|
.PP
|
||||||
|
Attribute `default\-groups`: The list of manifest groups to sync if no
|
||||||
|
`\-\-groups=` parameter was specified at init. When that list is empty, use this
|
||||||
|
list instead of "default" as the list of groups to sync.
|
||||||
|
.PP
|
||||||
Element project
|
Element project
|
||||||
.PP
|
.PP
|
||||||
One or more project elements may be specified. Each element describes a single
|
One or more project elements may be specified. Each element describes a single
|
||||||
@ -401,6 +487,12 @@ project. Same syntax as the corresponding element of `project`.
|
|||||||
Attribute `remote`: If specified, overrides the remote of the original project.
|
Attribute `remote`: If specified, overrides the remote of the original project.
|
||||||
Same syntax as the corresponding element of `project`.
|
Same syntax as the corresponding element of `project`.
|
||||||
.PP
|
.PP
|
||||||
|
Attribute `dest\-branch`: If specified, overrides the dest\-branch of the original
|
||||||
|
project. Same syntax as the corresponding element of `project`.
|
||||||
|
.PP
|
||||||
|
Attribute `upstream`: If specified, overrides the upstream of the original
|
||||||
|
project. Same syntax as the corresponding element of `project`.
|
||||||
|
.PP
|
||||||
Element annotation
|
Element annotation
|
||||||
.PP
|
.PP
|
||||||
Zero or more annotation elements may be specified as children of a project or
|
Zero or more annotation elements may be specified as children of a project or
|
||||||
@ -513,8 +605,8 @@ restrictions are not enforced for [Local Manifests].
|
|||||||
.PP
|
.PP
|
||||||
Attribute `groups`: List of additional groups to which all projects in the
|
Attribute `groups`: List of additional groups to which all projects in the
|
||||||
included manifest belong. This appends and recurses, meaning all projects in
|
included manifest belong. This appends and recurses, meaning all projects in
|
||||||
sub\-manifests carry all parent include groups. Same syntax as the corresponding
|
included manifests carry all parent include groups. Same syntax as the
|
||||||
element of `project`.
|
corresponding element of `project`.
|
||||||
.PP
|
.PP
|
||||||
Local Manifests
|
Local Manifests
|
||||||
.PP
|
.PP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo overview" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo overview" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo overview - manual page for repo overview
|
repo \- repo overview - manual page for repo overview
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -26,6 +26,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help overview` to view the detailed manual.
|
Run `repo help overview` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo prune" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo prune" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo prune - manual page for repo prune
|
repo \- repo prune - manual page for repo prune
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -24,5 +24,18 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help prune` to view the detailed manual.
|
Run `repo help prune` to view the detailed manual.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo rebase" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo rebase" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo rebase - manual page for repo rebase
|
repo \- repo rebase - manual page for repo rebase
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -46,6 +46,19 @@ only show errors
|
|||||||
.TP
|
.TP
|
||||||
\fB\-i\fR, \fB\-\-interactive\fR
|
\fB\-i\fR, \fB\-\-interactive\fR
|
||||||
interactive rebase (single project only)
|
interactive rebase (single project only)
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help rebase` to view the detailed manual.
|
Run `repo help rebase` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo selfupdate" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo selfupdate" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo selfupdate - manual page for repo selfupdate
|
repo \- repo selfupdate - manual page for repo selfupdate
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -20,6 +20,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.SS repo Version options:
|
.SS repo Version options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-repo\-verify\fR
|
\fB\-\-no\-repo\-verify\fR
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "November 2021" "repo smartsync" "Repo Manual"
|
.TH REPO "1" "August 2022" "repo smartsync" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo smartsync - manual page for repo smartsync
|
repo \- repo smartsync - manual page for repo smartsync
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -20,11 +20,11 @@ number of CPU cores)
|
|||||||
.TP
|
.TP
|
||||||
\fB\-\-jobs\-network\fR=\fI\,JOBS\/\fR
|
\fB\-\-jobs\-network\fR=\fI\,JOBS\/\fR
|
||||||
number of network jobs to run in parallel (defaults to
|
number of network jobs to run in parallel (defaults to
|
||||||
\fB\-\-jobs\fR)
|
\fB\-\-jobs\fR or 1)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-jobs\-checkout\fR=\fI\,JOBS\/\fR
|
\fB\-\-jobs\-checkout\fR=\fI\,JOBS\/\fR
|
||||||
number of local checkout jobs to run in parallel
|
number of local checkout jobs to run in parallel
|
||||||
(defaults to \fB\-\-jobs\fR)
|
(defaults to \fB\-\-jobs\fR or 8)
|
||||||
.TP
|
.TP
|
||||||
\fB\-f\fR, \fB\-\-force\-broken\fR
|
\fB\-f\fR, \fB\-\-force\-broken\fR
|
||||||
obsolete option (to be deleted in the future)
|
obsolete option (to be deleted in the future)
|
||||||
@ -112,6 +112,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.SS repo Version options:
|
.SS repo Version options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-repo\-verify\fR
|
\fB\-\-no\-repo\-verify\fR
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo stage" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo stage" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo stage - manual page for repo stage
|
repo \- repo stage - manual page for repo stage
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -23,6 +23,19 @@ only show errors
|
|||||||
.TP
|
.TP
|
||||||
\fB\-i\fR, \fB\-\-interactive\fR
|
\fB\-i\fR, \fB\-\-interactive\fR
|
||||||
use interactive staging
|
use interactive staging
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help stage` to view the detailed manual.
|
Run `repo help stage` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo start" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo start" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo start - manual page for repo start
|
repo \- repo start - manual page for repo start
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -33,6 +33,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help start` to view the detailed manual.
|
Run `repo help start` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo status" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo status" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo status - manual page for repo status
|
repo \- repo status - manual page for repo status
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -28,6 +28,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help status` to view the detailed manual.
|
Run `repo help status` to view the detailed manual.
|
||||||
.SH DETAILS
|
.SH DETAILS
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "November 2021" "repo sync" "Repo Manual"
|
.TH REPO "1" "August 2022" "repo sync" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo sync - manual page for repo sync
|
repo \- repo sync - manual page for repo sync
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -20,11 +20,11 @@ number of CPU cores)
|
|||||||
.TP
|
.TP
|
||||||
\fB\-\-jobs\-network\fR=\fI\,JOBS\/\fR
|
\fB\-\-jobs\-network\fR=\fI\,JOBS\/\fR
|
||||||
number of network jobs to run in parallel (defaults to
|
number of network jobs to run in parallel (defaults to
|
||||||
\fB\-\-jobs\fR)
|
\fB\-\-jobs\fR or 1)
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-jobs\-checkout\fR=\fI\,JOBS\/\fR
|
\fB\-\-jobs\-checkout\fR=\fI\,JOBS\/\fR
|
||||||
number of local checkout jobs to run in parallel
|
number of local checkout jobs to run in parallel
|
||||||
(defaults to \fB\-\-jobs\fR)
|
(defaults to \fB\-\-jobs\fR or 8)
|
||||||
.TP
|
.TP
|
||||||
\fB\-f\fR, \fB\-\-force\-broken\fR
|
\fB\-f\fR, \fB\-\-force\-broken\fR
|
||||||
obsolete option (to be deleted in the future)
|
obsolete option (to be deleted in the future)
|
||||||
@ -119,6 +119,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.SS repo Version options:
|
.SS repo Version options:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-repo\-verify\fR
|
\fB\-\-no\-repo\-verify\fR
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo upload" "Repo Manual"
|
.TH REPO "1" "August 2022" "repo upload" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo upload - manual page for repo upload
|
repo \- repo upload - manual page for repo upload
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -54,6 +54,9 @@ upload as a private change (deprecated; use \fB\-\-wip\fR)
|
|||||||
\fB\-w\fR, \fB\-\-wip\fR
|
\fB\-w\fR, \fB\-\-wip\fR
|
||||||
upload as a work\-in\-progress change
|
upload as a work\-in\-progress change
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-r\fR, \fB\-\-ready\fR
|
||||||
|
mark change as ready (clears work\-in\-progress setting)
|
||||||
|
.TP
|
||||||
\fB\-o\fR PUSH_OPTIONS, \fB\-\-push\-option\fR=\fI\,PUSH_OPTIONS\/\fR
|
\fB\-o\fR PUSH_OPTIONS, \fB\-\-push\-option\fR=\fI\,PUSH_OPTIONS\/\fR
|
||||||
additional push options to transmit
|
additional push options to transmit
|
||||||
.TP
|
.TP
|
||||||
@ -66,6 +69,12 @@ do everything except actually upload the CL
|
|||||||
\fB\-y\fR, \fB\-\-yes\fR
|
\fB\-y\fR, \fB\-\-yes\fR
|
||||||
answer yes to all safe prompts
|
answer yes to all safe prompts
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-\-ignore\-untracked\-files\fR
|
||||||
|
ignore untracked files in the working copy
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-ignore\-untracked\-files\fR
|
||||||
|
always ask about untracked files in the working copy
|
||||||
|
.TP
|
||||||
\fB\-\-no\-cert\-checks\fR
|
\fB\-\-no\-cert\-checks\fR
|
||||||
disable verifying ssl certs (unsafe)
|
disable verifying ssl certs (unsafe)
|
||||||
.SS Logging options:
|
.SS Logging options:
|
||||||
@ -75,6 +84,19 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.SS pre\-upload hooks:
|
.SS pre\-upload hooks:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-no\-verify\fR
|
\fB\-\-no\-verify\fR
|
||||||
@ -105,6 +127,12 @@ 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
|
\fB\-\-reviewers\fR must already be registered with the code review system, or the
|
||||||
upload will fail.
|
upload will fail.
|
||||||
.PP
|
.PP
|
||||||
|
While most normal Gerrit options have dedicated command line options, direct
|
||||||
|
access to the Gerit options is available via \fB\-\-push\-options\fR. This is useful when
|
||||||
|
Gerrit has newer functionality that repo upload doesn't yet support, or doesn't
|
||||||
|
have plans to support. See the Push Options documentation for more details:
|
||||||
|
https://gerrit\-review.googlesource.com/Documentation/user\-upload.html#push_options
|
||||||
|
.PP
|
||||||
Configuration
|
Configuration
|
||||||
.PP
|
.PP
|
||||||
review.URL.autoupload:
|
review.URL.autoupload:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "July 2021" "repo version" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo version" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repo version - manual page for repo version
|
repo \- repo version - manual page for repo version
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -20,5 +20,18 @@ show all output
|
|||||||
.TP
|
.TP
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
only show errors
|
only show errors
|
||||||
|
.SS Multi\-manifest options:
|
||||||
|
.TP
|
||||||
|
\fB\-\-outer\-manifest\fR
|
||||||
|
operate starting at the outermost manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-outer\-manifest\fR
|
||||||
|
do not operate on outer manifests
|
||||||
|
.TP
|
||||||
|
\fB\-\-this\-manifest\-only\fR
|
||||||
|
only operate on this (sub)manifest
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-this\-manifest\-only\fR, \fB\-\-all\-manifests\fR
|
||||||
|
operate on this manifest and its submanifests
|
||||||
.PP
|
.PP
|
||||||
Run `repo help version` to view the detailed manual.
|
Run `repo help version` to view the detailed manual.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
.\" DO NOT MODIFY THIS FILE! It was generated by help2man.
|
||||||
.TH REPO "1" "November 2021" "repo" "Repo Manual"
|
.TH REPO "1" "July 2022" "repo" "Repo Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
repo \- repository management tool built on top of git
|
repo \- repository management tool built on top of git
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -43,6 +43,9 @@ filename of event log to append timeline to
|
|||||||
.TP
|
.TP
|
||||||
\fB\-\-git\-trace2\-event\-log\fR=\fI\,GIT_TRACE2_EVENT_LOG\/\fR
|
\fB\-\-git\-trace2\-event\-log\fR=\fI\,GIT_TRACE2_EVENT_LOG\/\fR
|
||||||
directory to write git trace2 event log to
|
directory to write git trace2 event log to
|
||||||
|
.TP
|
||||||
|
\fB\-\-submanifest\-path\fR=\fI\,REL_PATH\/\fR
|
||||||
|
submanifest path
|
||||||
.SS "The complete list of recognized repo commands is:"
|
.SS "The complete list of recognized repo commands is:"
|
||||||
.TP
|
.TP
|
||||||
abandon
|
abandon
|
||||||
|
169
manifest_xml.py
169
manifest_xml.py
@ -123,7 +123,7 @@ class _Default(object):
|
|||||||
destBranchExpr = None
|
destBranchExpr = None
|
||||||
upstreamExpr = None
|
upstreamExpr = None
|
||||||
remote = None
|
remote = None
|
||||||
sync_j = 1
|
sync_j = None
|
||||||
sync_c = False
|
sync_c = False
|
||||||
sync_s = False
|
sync_s = False
|
||||||
sync_tags = True
|
sync_tags = True
|
||||||
@ -214,9 +214,11 @@ class _XmlSubmanifest:
|
|||||||
revision: a string, the commitish.
|
revision: a string, the commitish.
|
||||||
manifestName: a string, the submanifest file name.
|
manifestName: a string, the submanifest file name.
|
||||||
groups: a list of strings, the groups to add to all projects in the submanifest.
|
groups: a list of strings, the groups to add to all projects in the submanifest.
|
||||||
|
default_groups: a list of strings, the default groups to sync.
|
||||||
path: a string, the relative path for the submanifest checkout.
|
path: a string, the relative path for the submanifest checkout.
|
||||||
|
parent: an XmlManifest, the parent manifest.
|
||||||
annotations: (derived) a list of annotations.
|
annotations: (derived) a list of annotations.
|
||||||
present: (derived) a boolean, whether the submanifest's manifest file is present.
|
present: (derived) a boolean, whether the sub manifest file is present.
|
||||||
"""
|
"""
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
name,
|
||||||
@ -225,6 +227,7 @@ class _XmlSubmanifest:
|
|||||||
revision=None,
|
revision=None,
|
||||||
manifestName=None,
|
manifestName=None,
|
||||||
groups=None,
|
groups=None,
|
||||||
|
default_groups=None,
|
||||||
path=None,
|
path=None,
|
||||||
parent=None):
|
parent=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -233,7 +236,9 @@ class _XmlSubmanifest:
|
|||||||
self.revision = revision
|
self.revision = revision
|
||||||
self.manifestName = manifestName
|
self.manifestName = manifestName
|
||||||
self.groups = groups
|
self.groups = groups
|
||||||
|
self.default_groups = default_groups
|
||||||
self.path = path
|
self.path = path
|
||||||
|
self.parent = parent
|
||||||
self.annotations = []
|
self.annotations = []
|
||||||
outer_client = parent._outer_client or parent
|
outer_client = parent._outer_client or parent
|
||||||
if self.remote and not self.project:
|
if self.remote and not self.project:
|
||||||
@ -248,7 +253,8 @@ class _XmlSubmanifest:
|
|||||||
os.path.join(parent.path_prefix, self.relpath), MANIFEST_FILE_NAME)
|
os.path.join(parent.path_prefix, self.relpath), MANIFEST_FILE_NAME)
|
||||||
rc = self.repo_client = RepoClient(
|
rc = self.repo_client = RepoClient(
|
||||||
parent.repodir, linkFile, parent_groups=','.join(groups) or '',
|
parent.repodir, linkFile, parent_groups=','.join(groups) or '',
|
||||||
submanifest_path=self.relpath, outer_client=outer_client)
|
submanifest_path=self.relpath, outer_client=outer_client,
|
||||||
|
default_groups=default_groups)
|
||||||
|
|
||||||
self.present = os.path.exists(manifestFile)
|
self.present = os.path.exists(manifestFile)
|
||||||
|
|
||||||
@ -262,26 +268,28 @@ class _XmlSubmanifest:
|
|||||||
self.revision == other.revision and
|
self.revision == other.revision and
|
||||||
self.manifestName == other.manifestName and
|
self.manifestName == other.manifestName and
|
||||||
self.groups == other.groups and
|
self.groups == other.groups and
|
||||||
|
self.default_groups == other.default_groups and
|
||||||
self.path == other.path and
|
self.path == other.path and
|
||||||
sorted(self.annotations) == sorted(other.annotations))
|
sorted(self.annotations) == sorted(other.annotations))
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self.__eq__(other)
|
return not self.__eq__(other)
|
||||||
|
|
||||||
def ToSubmanifestSpec(self, root):
|
def ToSubmanifestSpec(self):
|
||||||
"""Return a SubmanifestSpec object, populating attributes"""
|
"""Return a SubmanifestSpec object, populating attributes"""
|
||||||
mp = root.manifestProject
|
mp = self.parent.manifestProject
|
||||||
remote = root.remotes[self.remote or root.default.remote.name]
|
remote = self.parent.remotes[self.remote or self.parent.default.remote.name]
|
||||||
# If a project was given, generate the url from the remote and project.
|
# If a project was given, generate the url from the remote and project.
|
||||||
# If not, use this manifestProject's url.
|
# If not, use this manifestProject's url.
|
||||||
if self.project:
|
if self.project:
|
||||||
manifestUrl = remote.ToRemoteSpec(self.project).url
|
manifestUrl = remote.ToRemoteSpec(self.project).url
|
||||||
else:
|
else:
|
||||||
manifestUrl = mp.GetRemote(mp.remote.name).url
|
manifestUrl = mp.GetRemote().url
|
||||||
manifestName = self.manifestName or 'default.xml'
|
manifestName = self.manifestName or 'default.xml'
|
||||||
revision = self.revision or self.name
|
revision = self.revision or self.name
|
||||||
path = self.path or revision.split('/')[-1]
|
path = self.path or revision.split('/')[-1]
|
||||||
groups = self.groups or []
|
groups = self.groups or []
|
||||||
|
default_groups = self.default_groups or []
|
||||||
|
|
||||||
return SubmanifestSpec(self.name, manifestUrl, manifestName, revision, path,
|
return SubmanifestSpec(self.name, manifestUrl, manifestName, revision, path,
|
||||||
groups)
|
groups)
|
||||||
@ -298,6 +306,10 @@ class _XmlSubmanifest:
|
|||||||
return ','.join(self.groups)
|
return ','.join(self.groups)
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
def GetDefaultGroupsStr(self):
|
||||||
|
"""Returns the `default-groups` given for this submanifest."""
|
||||||
|
return ','.join(self.default_groups or [])
|
||||||
|
|
||||||
def AddAnnotation(self, name, value, keep):
|
def AddAnnotation(self, name, value, keep):
|
||||||
"""Add annotations to the submanifest."""
|
"""Add annotations to the submanifest."""
|
||||||
self.annotations.append(Annotation(name, value, keep))
|
self.annotations.append(Annotation(name, value, keep))
|
||||||
@ -325,7 +337,8 @@ class XmlManifest(object):
|
|||||||
"""manages the repo configuration file"""
|
"""manages the repo configuration file"""
|
||||||
|
|
||||||
def __init__(self, repodir, manifest_file, local_manifests=None,
|
def __init__(self, repodir, manifest_file, local_manifests=None,
|
||||||
outer_client=None, parent_groups='', submanifest_path=''):
|
outer_client=None, parent_groups='', submanifest_path='',
|
||||||
|
default_groups=None):
|
||||||
"""Initialize.
|
"""Initialize.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -335,22 +348,32 @@ class XmlManifest(object):
|
|||||||
be |repodir|/|MANIFEST_FILE_NAME|.
|
be |repodir|/|MANIFEST_FILE_NAME|.
|
||||||
local_manifests: Full path to the directory of local override manifests.
|
local_manifests: Full path to the directory of local override manifests.
|
||||||
This will usually be |repodir|/|LOCAL_MANIFESTS_DIR_NAME|.
|
This will usually be |repodir|/|LOCAL_MANIFESTS_DIR_NAME|.
|
||||||
outer_client: RepoClient of the outertree.
|
outer_client: RepoClient of the outer manifest.
|
||||||
parent_groups: a string, the groups to apply to this projects.
|
parent_groups: a string, the groups to apply to this projects.
|
||||||
submanifest_path: The submanifest root relative to the repo root.
|
submanifest_path: The submanifest root relative to the repo root.
|
||||||
|
default_groups: a string, the default manifest groups to use.
|
||||||
"""
|
"""
|
||||||
# TODO(vapier): Move this out of this class.
|
# TODO(vapier): Move this out of this class.
|
||||||
self.globalConfig = GitConfig.ForUser()
|
self.globalConfig = GitConfig.ForUser()
|
||||||
|
|
||||||
self.repodir = os.path.abspath(repodir)
|
self.repodir = os.path.abspath(repodir)
|
||||||
self._CheckLocalPath(submanifest_path)
|
self._CheckLocalPath(submanifest_path)
|
||||||
self.topdir = os.path.join(os.path.dirname(self.repodir), submanifest_path)
|
self.topdir = os.path.dirname(self.repodir)
|
||||||
|
if submanifest_path:
|
||||||
|
# This avoids a trailing os.path.sep when submanifest_path is empty.
|
||||||
|
self.topdir = os.path.join(self.topdir, submanifest_path)
|
||||||
if manifest_file != os.path.abspath(manifest_file):
|
if manifest_file != os.path.abspath(manifest_file):
|
||||||
raise ManifestParseError('manifest_file must be abspath')
|
raise ManifestParseError('manifest_file must be abspath')
|
||||||
self.manifestFile = manifest_file
|
self.manifestFile = manifest_file
|
||||||
|
if not outer_client or outer_client == self:
|
||||||
|
# manifestFileOverrides only exists in the outer_client's manifest, since
|
||||||
|
# that is the only instance left when Unload() is called on the outer
|
||||||
|
# manifest.
|
||||||
|
self.manifestFileOverrides = {}
|
||||||
self.local_manifests = local_manifests
|
self.local_manifests = local_manifests
|
||||||
self._load_local_manifests = True
|
self._load_local_manifests = True
|
||||||
self.parent_groups = parent_groups
|
self.parent_groups = parent_groups
|
||||||
|
self.default_groups = default_groups
|
||||||
|
|
||||||
if outer_client and self.isGitcClient:
|
if outer_client and self.isGitcClient:
|
||||||
raise ManifestParseError('Multi-manifest is incompatible with `gitc-init`')
|
raise ManifestParseError('Multi-manifest is incompatible with `gitc-init`')
|
||||||
@ -396,14 +419,10 @@ class XmlManifest(object):
|
|||||||
if not os.path.isfile(path):
|
if not os.path.isfile(path):
|
||||||
raise ManifestParseError('manifest %s not found' % name)
|
raise ManifestParseError('manifest %s not found' % name)
|
||||||
|
|
||||||
old = self.manifestFile
|
|
||||||
try:
|
|
||||||
self._load_local_manifests = load_local_manifests
|
self._load_local_manifests = load_local_manifests
|
||||||
self.manifestFile = path
|
self._outer_client.manifestFileOverrides[self.path_prefix] = path
|
||||||
self.Unload()
|
self.Unload()
|
||||||
self._Load()
|
self._Load()
|
||||||
finally:
|
|
||||||
self.manifestFile = old
|
|
||||||
|
|
||||||
def Link(self, name):
|
def Link(self, name):
|
||||||
"""Update the repo metadata to use a different manifest.
|
"""Update the repo metadata to use a different manifest.
|
||||||
@ -469,6 +488,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
e.setAttribute('path', r.path)
|
e.setAttribute('path', r.path)
|
||||||
if r.groups:
|
if r.groups:
|
||||||
e.setAttribute('groups', r.GetGroupsStr())
|
e.setAttribute('groups', r.GetGroupsStr())
|
||||||
|
if r.default_groups:
|
||||||
|
e.setAttribute('default-groups', r.GetDefaultGroupsStr())
|
||||||
|
|
||||||
for a in r.annotations:
|
for a in r.annotations:
|
||||||
if a.keep == 'true':
|
if a.keep == 'true':
|
||||||
@ -484,7 +505,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
"""
|
"""
|
||||||
return [x for x in re.split(r'[,\s]+', field) if x]
|
return [x for x in re.split(r'[,\s]+', field) if x]
|
||||||
|
|
||||||
def ToXml(self, peg_rev=False, peg_rev_upstream=True, peg_rev_dest_branch=True, groups=None):
|
def ToXml(self, peg_rev=False, peg_rev_upstream=True,
|
||||||
|
peg_rev_dest_branch=True, groups=None, omit_local=False):
|
||||||
"""Return the current manifest XML."""
|
"""Return the current manifest XML."""
|
||||||
mp = self.manifestProject
|
mp = self.manifestProject
|
||||||
|
|
||||||
@ -529,7 +551,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
if d.upstreamExpr:
|
if d.upstreamExpr:
|
||||||
have_default = True
|
have_default = True
|
||||||
e.setAttribute('upstream', d.upstreamExpr)
|
e.setAttribute('upstream', d.upstreamExpr)
|
||||||
if d.sync_j > 1:
|
if d.sync_j is not None:
|
||||||
have_default = True
|
have_default = True
|
||||||
e.setAttribute('sync-j', '%d' % d.sync_j)
|
e.setAttribute('sync-j', '%d' % d.sync_j)
|
||||||
if d.sync_c:
|
if d.sync_c:
|
||||||
@ -565,6 +587,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
if not p.MatchesGroups(groups):
|
if not p.MatchesGroups(groups):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if omit_local and self.IsFromLocalManifest(p):
|
||||||
|
return
|
||||||
|
|
||||||
name = p.name
|
name = p.name
|
||||||
relpath = p.relpath
|
relpath = p.relpath
|
||||||
if parent:
|
if parent:
|
||||||
@ -750,23 +775,29 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def is_multimanifest(self):
|
def is_multimanifest(self):
|
||||||
"""Whether this is a multimanifest checkout"""
|
"""Whether this is a multimanifest checkout.
|
||||||
return bool(self.outer_client.submanifests)
|
|
||||||
|
This is safe to use as long as the outermost manifest XML has been parsed.
|
||||||
|
"""
|
||||||
|
return bool(self._outer_client._submanifests)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_submanifest(self):
|
def is_submanifest(self):
|
||||||
"""Whether this manifest is a submanifest"""
|
"""Whether this manifest is a submanifest.
|
||||||
|
|
||||||
|
This is safe to use as long as the outermost manifest XML has been parsed.
|
||||||
|
"""
|
||||||
return self._outer_client and self._outer_client != self
|
return self._outer_client and self._outer_client != self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def outer_client(self):
|
def outer_client(self):
|
||||||
"""The instance of the outermost manifest client"""
|
"""The instance of the outermost manifest client."""
|
||||||
self._Load()
|
self._Load()
|
||||||
return self._outer_client
|
return self._outer_client
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def all_manifests(self):
|
def all_manifests(self):
|
||||||
"""Generator yielding all (sub)manifests."""
|
"""Generator yielding all (sub)manifests, in depth-first order."""
|
||||||
self._Load()
|
self._Load()
|
||||||
outer = self._outer_client
|
outer = self._outer_client
|
||||||
yield outer
|
yield outer
|
||||||
@ -775,7 +806,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def all_children(self):
|
def all_children(self):
|
||||||
"""Generator yielding all child submanifests."""
|
"""Generator yielding all (present) child submanifests."""
|
||||||
self._Load()
|
self._Load()
|
||||||
for child in self._submanifests.values():
|
for child in self._submanifests.values():
|
||||||
if child.repo_client:
|
if child.repo_client:
|
||||||
@ -792,7 +823,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def all_paths(self):
|
def all_paths(self):
|
||||||
"""All project paths for all (sub)manifests. See `paths`."""
|
"""All project paths for all (sub)manifests.
|
||||||
|
|
||||||
|
See also `paths`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary of {path: Project()}. `path` is relative to the outer
|
||||||
|
manifest.
|
||||||
|
"""
|
||||||
ret = {}
|
ret = {}
|
||||||
for tree in self.all_manifests:
|
for tree in self.all_manifests:
|
||||||
prefix = tree.path_prefix
|
prefix = tree.path_prefix
|
||||||
@ -808,7 +846,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
def paths(self):
|
def paths(self):
|
||||||
"""Return all paths for this manifest.
|
"""Return all paths for this manifest.
|
||||||
|
|
||||||
Return:
|
Returns:
|
||||||
A dictionary of {path: Project()}. `path` is relative to this manifest.
|
A dictionary of {path: Project()}. `path` is relative to this manifest.
|
||||||
"""
|
"""
|
||||||
self._Load()
|
self._Load()
|
||||||
@ -822,11 +860,13 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def remotes(self):
|
def remotes(self):
|
||||||
|
"""Return a list of remotes for this manifest."""
|
||||||
self._Load()
|
self._Load()
|
||||||
return self._remotes
|
return self._remotes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default(self):
|
def default(self):
|
||||||
|
"""Return default values for this manifest."""
|
||||||
self._Load()
|
self._Load()
|
||||||
return self._default
|
return self._default
|
||||||
|
|
||||||
@ -880,6 +920,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
exclude = self.manifest.manifestProject.partial_clone_exclude or ''
|
exclude = self.manifest.manifestProject.partial_clone_exclude or ''
|
||||||
return set(x.strip() for x in exclude.split(','))
|
return set(x.strip() for x in exclude.split(','))
|
||||||
|
|
||||||
|
def SetManifestOverride(self, path):
|
||||||
|
"""Override manifestFile. The caller must call Unload()"""
|
||||||
|
self._outer_client.manifest.manifestFileOverrides[self.path_prefix] = path
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def UseLocalManifests(self):
|
def UseLocalManifests(self):
|
||||||
return self._load_local_manifests
|
return self._load_local_manifests
|
||||||
@ -960,16 +1004,21 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
worktree=os.path.join(subdir, 'manifests'))
|
worktree=os.path.join(subdir, 'manifests'))
|
||||||
return mp
|
return mp
|
||||||
|
|
||||||
def GetDefaultGroupsStr(self):
|
def GetDefaultGroupsStr(self, with_platform=True):
|
||||||
"""Returns the default group string for the platform."""
|
"""Returns the default group string to use.
|
||||||
return 'default,platform-' + platform.system().lower()
|
|
||||||
|
Args:
|
||||||
|
with_platform: a boolean, whether to include the group for the
|
||||||
|
underlying platform.
|
||||||
|
"""
|
||||||
|
groups = ','.join(self.default_groups or ['default'])
|
||||||
|
if with_platform:
|
||||||
|
groups += f',platform-{platform.system().lower()}'
|
||||||
|
return groups
|
||||||
|
|
||||||
def GetGroupsStr(self):
|
def GetGroupsStr(self):
|
||||||
"""Returns the manifest group string that should be synced."""
|
"""Returns the manifest group string that should be synced."""
|
||||||
groups = self.manifestProject.manifest_groups
|
return self.manifestProject.manifest_groups or self.GetDefaultGroupsStr()
|
||||||
if not groups:
|
|
||||||
groups = self.GetDefaultGroupsStr()
|
|
||||||
return groups
|
|
||||||
|
|
||||||
def Unload(self):
|
def Unload(self):
|
||||||
"""Unload the manifest.
|
"""Unload the manifest.
|
||||||
@ -1005,6 +1054,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
# This will load all clients.
|
# This will load all clients.
|
||||||
self._outer_client._Load(initial_client=self)
|
self._outer_client._Load(initial_client=self)
|
||||||
|
|
||||||
|
savedManifestFile = self.manifestFile
|
||||||
|
override = self._outer_client.manifestFileOverrides.get(self.path_prefix)
|
||||||
|
if override:
|
||||||
|
self.manifestFile = override
|
||||||
|
|
||||||
|
try:
|
||||||
m = self.manifestProject
|
m = self.manifestProject
|
||||||
b = m.GetBranch(m.CurrentBranch).merge
|
b = m.GetBranch(m.CurrentBranch).merge
|
||||||
if b is not None and b.startswith(R_HEADS):
|
if b is not None and b.startswith(R_HEADS):
|
||||||
@ -1050,12 +1105,15 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
self._AddMetaProjectMirror(self.manifestProject)
|
self._AddMetaProjectMirror(self.manifestProject)
|
||||||
|
|
||||||
self._loaded = True
|
self._loaded = True
|
||||||
|
finally:
|
||||||
|
if override:
|
||||||
|
self.manifestFile = savedManifestFile
|
||||||
|
|
||||||
# Now that we have loaded this manifest, load any submanifest manifests
|
# Now that we have loaded this manifest, load any submanifests as well.
|
||||||
# as well. We need to do this after self._loaded is set to avoid looping.
|
# We need to do this after self._loaded is set to avoid looping.
|
||||||
for name in self._submanifests:
|
for name in self._submanifests:
|
||||||
tree = self._submanifests[name]
|
tree = self._submanifests[name]
|
||||||
spec = tree.ToSubmanifestSpec(self)
|
spec = tree.ToSubmanifestSpec()
|
||||||
present = os.path.exists(os.path.join(self.subdir, MANIFEST_FILE_NAME))
|
present = os.path.exists(os.path.join(self.subdir, MANIFEST_FILE_NAME))
|
||||||
if present and tree.present and not tree.repo_client:
|
if present and tree.present and not tree.repo_client:
|
||||||
if initial_client and initial_client.topdir == self.topdir:
|
if initial_client and initial_client.topdir == self.topdir:
|
||||||
@ -1231,6 +1289,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
remote = self._default.remote
|
remote = self._default.remote
|
||||||
else:
|
else:
|
||||||
remote = self._get_remote(node)
|
remote = self._get_remote(node)
|
||||||
|
dest_branch = node.getAttribute('dest-branch')
|
||||||
|
upstream = node.getAttribute('upstream')
|
||||||
|
|
||||||
named_projects = self._projects[name]
|
named_projects = self._projects[name]
|
||||||
if dest_path and not path and len(named_projects) > 1:
|
if dest_path and not path and len(named_projects) > 1:
|
||||||
@ -1246,6 +1306,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
if remote_name:
|
if remote_name:
|
||||||
p.remote = remote.ToRemoteSpec(name)
|
p.remote = remote.ToRemoteSpec(name)
|
||||||
|
if dest_branch:
|
||||||
|
p.dest_branch = dest_branch
|
||||||
|
if upstream:
|
||||||
|
p.upstream = upstream
|
||||||
|
|
||||||
if dest_path:
|
if dest_path:
|
||||||
del self._paths[p.relpath]
|
del self._paths[p.relpath]
|
||||||
@ -1330,7 +1394,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
|
|
||||||
def _AddMetaProjectMirror(self, m):
|
def _AddMetaProjectMirror(self, m):
|
||||||
name = None
|
name = None
|
||||||
m_url = m.GetRemote(m.remote.name).url
|
m_url = m.GetRemote().url
|
||||||
if m_url.endswith('/.git'):
|
if m_url.endswith('/.git'):
|
||||||
raise ManifestParseError('refusing to mirror %s' % m_url)
|
raise ManifestParseError('refusing to mirror %s' % m_url)
|
||||||
|
|
||||||
@ -1407,8 +1471,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
d.destBranchExpr = node.getAttribute('dest-branch') or None
|
d.destBranchExpr = node.getAttribute('dest-branch') or None
|
||||||
d.upstreamExpr = node.getAttribute('upstream') or None
|
d.upstreamExpr = node.getAttribute('upstream') or None
|
||||||
|
|
||||||
d.sync_j = XmlInt(node, 'sync-j', 1)
|
d.sync_j = XmlInt(node, 'sync-j', None)
|
||||||
if d.sync_j <= 0:
|
if d.sync_j is not None and d.sync_j <= 0:
|
||||||
raise ManifestParseError('%s: sync-j must be greater than 0, not "%s"' %
|
raise ManifestParseError('%s: sync-j must be greater than 0, not "%s"' %
|
||||||
(self.manifestFile, d.sync_j))
|
(self.manifestFile, d.sync_j))
|
||||||
|
|
||||||
@ -1475,6 +1539,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
if node.hasAttribute('groups'):
|
if node.hasAttribute('groups'):
|
||||||
groups = node.getAttribute('groups')
|
groups = node.getAttribute('groups')
|
||||||
groups = self._ParseList(groups)
|
groups = self._ParseList(groups)
|
||||||
|
default_groups = self._ParseList(node.getAttribute('default-groups'))
|
||||||
path = node.getAttribute('path')
|
path = node.getAttribute('path')
|
||||||
if path == '':
|
if path == '':
|
||||||
path = None
|
path = None
|
||||||
@ -1495,7 +1560,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
'<submanifest> invalid "path": %s: %s' % (path, msg))
|
'<submanifest> invalid "path": %s: %s' % (path, msg))
|
||||||
|
|
||||||
submanifest = _XmlSubmanifest(name, remote, project, revision, manifestName,
|
submanifest = _XmlSubmanifest(name, remote, project, revision, manifestName,
|
||||||
groups, path, self)
|
groups, default_groups, path, self)
|
||||||
|
|
||||||
for n in node.childNodes:
|
for n in node.childNodes:
|
||||||
if n.nodeName == 'annotation':
|
if n.nodeName == 'annotation':
|
||||||
@ -1619,6 +1684,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
name: a string, the name of the project.
|
name: a string, the name of the project.
|
||||||
path: a string, the path of the project.
|
path: a string, the path of the project.
|
||||||
remote: a string, the remote.name of the project.
|
remote: a string, the remote.name of the project.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A tuple of (relpath, worktree, gitdir, objdir, use_git_worktrees) for the
|
||||||
|
project with |name| and |path|.
|
||||||
"""
|
"""
|
||||||
# The manifest entries might have trailing slashes. Normalize them to avoid
|
# The manifest entries might have trailing slashes. Normalize them to avoid
|
||||||
# unexpected filesystem behavior since we do string concatenation below.
|
# unexpected filesystem behavior since we do string concatenation below.
|
||||||
@ -1626,7 +1695,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
name = name.rstrip('/')
|
name = name.rstrip('/')
|
||||||
remote = remote.rstrip('/')
|
remote = remote.rstrip('/')
|
||||||
use_git_worktrees = False
|
use_git_worktrees = False
|
||||||
use_remote_name = bool(self._outer_client._submanifests)
|
use_remote_name = self.is_multimanifest
|
||||||
relpath = path
|
relpath = path
|
||||||
if self.IsMirror:
|
if self.IsMirror:
|
||||||
worktree = None
|
worktree = None
|
||||||
@ -1642,7 +1711,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
# We allow people to mix git worktrees & non-git worktrees for now.
|
# We allow people to mix git worktrees & non-git worktrees for now.
|
||||||
# This allows for in situ migration of repo clients.
|
# This allows for in situ migration of repo clients.
|
||||||
if os.path.exists(gitdir) or not self.UseGitWorktrees:
|
if os.path.exists(gitdir) or not self.UseGitWorktrees:
|
||||||
objdir = os.path.join(self.subdir, 'project-objects', namepath)
|
objdir = os.path.join(self.repodir, 'project-objects', namepath)
|
||||||
else:
|
else:
|
||||||
use_git_worktrees = True
|
use_git_worktrees = True
|
||||||
gitdir = os.path.join(self.repodir, 'worktrees', namepath)
|
gitdir = os.path.join(self.repodir, 'worktrees', namepath)
|
||||||
@ -1656,6 +1725,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
name: a string, the name of the project.
|
name: a string, the name of the project.
|
||||||
all_manifests: a boolean, if True, then all manifests are searched. If
|
all_manifests: a boolean, if True, then all manifests are searched. If
|
||||||
False, then only this manifest is searched.
|
False, then only this manifest is searched.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of Project instances with name |name|.
|
||||||
"""
|
"""
|
||||||
if all_manifests:
|
if all_manifests:
|
||||||
return list(itertools.chain.from_iterable(
|
return list(itertools.chain.from_iterable(
|
||||||
@ -1874,11 +1946,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
|
|||||||
fromKeys = sorted(fromProjects.keys())
|
fromKeys = sorted(fromProjects.keys())
|
||||||
toKeys = sorted(toProjects.keys())
|
toKeys = sorted(toProjects.keys())
|
||||||
|
|
||||||
diff = {'added': [], 'removed': [], 'changed': [], 'unreachable': []}
|
diff = {'added': [], 'removed': [], 'missing': [], 'changed': [], 'unreachable': []}
|
||||||
|
|
||||||
for proj in fromKeys:
|
for proj in fromKeys:
|
||||||
if proj not in toKeys:
|
if proj not in toKeys:
|
||||||
diff['removed'].append(fromProjects[proj])
|
diff['removed'].append(fromProjects[proj])
|
||||||
|
elif not fromProjects[proj].Exists:
|
||||||
|
diff['missing'].append(toProjects[proj])
|
||||||
|
toKeys.remove(proj)
|
||||||
else:
|
else:
|
||||||
fromProj = fromProjects[proj]
|
fromProj = fromProjects[proj]
|
||||||
toProj = toProjects[proj]
|
toProj = toProjects[proj]
|
||||||
@ -1916,6 +1991,16 @@ class RepoClient(XmlManifest):
|
|||||||
"""Manages a repo client checkout."""
|
"""Manages a repo client checkout."""
|
||||||
|
|
||||||
def __init__(self, repodir, manifest_file=None, submanifest_path='', **kwargs):
|
def __init__(self, repodir, manifest_file=None, submanifest_path='', **kwargs):
|
||||||
|
"""Initialize.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
repodir: Path to the .repo/ dir for holding all internal checkout state.
|
||||||
|
It must be in the top directory of the repo client checkout.
|
||||||
|
manifest_file: Full path to the manifest file to parse. This will usually
|
||||||
|
be |repodir|/|MANIFEST_FILE_NAME|.
|
||||||
|
submanifest_path: The submanifest root relative to the repo root.
|
||||||
|
**kwargs: Additional keyword arguments, passed to XmlManifest.
|
||||||
|
"""
|
||||||
self.isGitcClient = False
|
self.isGitcClient = False
|
||||||
submanifest_path = submanifest_path or ''
|
submanifest_path = submanifest_path or ''
|
||||||
if submanifest_path:
|
if submanifest_path:
|
||||||
|
3
pager.py
3
pager.py
@ -56,8 +56,11 @@ def _PipePager(pager):
|
|||||||
global pager_process, old_stdout, old_stderr
|
global pager_process, old_stdout, old_stderr
|
||||||
assert pager_process is None, "Only one active pager process at a time"
|
assert pager_process is None, "Only one active pager process at a time"
|
||||||
# Create pager process, piping stdout/err into its stdin
|
# Create pager process, piping stdout/err into its stdin
|
||||||
|
try:
|
||||||
pager_process = subprocess.Popen([pager], stdin=subprocess.PIPE, stdout=sys.stdout,
|
pager_process = subprocess.Popen([pager], stdin=subprocess.PIPE, stdout=sys.stdout,
|
||||||
stderr=sys.stderr)
|
stderr=sys.stderr)
|
||||||
|
except FileNotFoundError:
|
||||||
|
sys.exit(f'fatal: cannot start pager "{pager}"')
|
||||||
old_stdout = sys.stdout
|
old_stdout = sys.stdout
|
||||||
old_stderr = sys.stderr
|
old_stderr = sys.stderr
|
||||||
sys.stdout = pager_process.stdin
|
sys.stdout = pager_process.stdin
|
||||||
|
27
progress.py
27
progress.py
@ -24,6 +24,11 @@ _NOT_TTY = not os.isatty(2)
|
|||||||
# column 0.
|
# column 0.
|
||||||
CSI_ERASE_LINE = '\x1b[2K'
|
CSI_ERASE_LINE = '\x1b[2K'
|
||||||
|
|
||||||
|
# This will erase all content in the current line after the cursor. This is
|
||||||
|
# useful for partial updates & progress messages as the terminal can display
|
||||||
|
# it better.
|
||||||
|
CSI_ERASE_LINE_AFTER = '\x1b[K'
|
||||||
|
|
||||||
|
|
||||||
def duration_str(total):
|
def duration_str(total):
|
||||||
"""A less noisy timedelta.__str__.
|
"""A less noisy timedelta.__str__.
|
||||||
@ -85,10 +90,10 @@ class Progress(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if self._total <= 0:
|
if self._total <= 0:
|
||||||
sys.stderr.write('%s\r%s: %d,' % (
|
sys.stderr.write('\r%s: %d,%s' % (
|
||||||
CSI_ERASE_LINE,
|
|
||||||
self._title,
|
self._title,
|
||||||
self._done))
|
self._done,
|
||||||
|
CSI_ERASE_LINE_AFTER))
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
else:
|
else:
|
||||||
p = (100 * self._done) / self._total
|
p = (100 * self._done) / self._total
|
||||||
@ -96,14 +101,14 @@ class Progress(object):
|
|||||||
jobs = '[%d job%s] ' % (self._active, 's' if self._active > 1 else '')
|
jobs = '[%d job%s] ' % (self._active, 's' if self._active > 1 else '')
|
||||||
else:
|
else:
|
||||||
jobs = ''
|
jobs = ''
|
||||||
sys.stderr.write('%s\r%s: %2d%% %s(%d%s/%d%s)%s%s%s' % (
|
sys.stderr.write('\r%s: %2d%% %s(%d%s/%d%s)%s%s%s%s' % (
|
||||||
CSI_ERASE_LINE,
|
|
||||||
self._title,
|
self._title,
|
||||||
p,
|
p,
|
||||||
jobs,
|
jobs,
|
||||||
self._done, self._units,
|
self._done, self._units,
|
||||||
self._total, self._units,
|
self._total, self._units,
|
||||||
' ' if msg else '', msg,
|
' ' if msg else '', msg,
|
||||||
|
CSI_ERASE_LINE_AFTER,
|
||||||
'\n' if self._print_newline else ''))
|
'\n' if self._print_newline else ''))
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
|
||||||
@ -113,19 +118,19 @@ class Progress(object):
|
|||||||
|
|
||||||
duration = duration_str(time() - self._start)
|
duration = duration_str(time() - self._start)
|
||||||
if self._total <= 0:
|
if self._total <= 0:
|
||||||
sys.stderr.write('%s\r%s: %d, done in %s\n' % (
|
sys.stderr.write('\r%s: %d, done in %s%s\n' % (
|
||||||
CSI_ERASE_LINE,
|
|
||||||
self._title,
|
self._title,
|
||||||
self._done,
|
self._done,
|
||||||
duration))
|
duration,
|
||||||
|
CSI_ERASE_LINE_AFTER))
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
else:
|
else:
|
||||||
p = (100 * self._done) / self._total
|
p = (100 * self._done) / self._total
|
||||||
sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s), done in %s\n' % (
|
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done in %s%s\n' % (
|
||||||
CSI_ERASE_LINE,
|
|
||||||
self._title,
|
self._title,
|
||||||
p,
|
p,
|
||||||
self._done, self._units,
|
self._done, self._units,
|
||||||
self._total, self._units,
|
self._total, self._units,
|
||||||
duration))
|
duration,
|
||||||
|
CSI_ERASE_LINE_AFTER))
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
318
project.py
318
project.py
@ -26,12 +26,15 @@ import sys
|
|||||||
import tarfile
|
import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
from typing import NamedTuple
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
from color import Coloring
|
from color import Coloring
|
||||||
|
import fetch
|
||||||
from git_command import GitCommand, git_require
|
from git_command import GitCommand, git_require
|
||||||
from git_config import GitConfig, IsId, GetSchemeFromUrl, GetUrlCookieFile, \
|
from git_config import GitConfig, IsId, GetSchemeFromUrl, GetUrlCookieFile, \
|
||||||
ID_RE
|
ID_RE
|
||||||
|
import git_superproject
|
||||||
from git_trace2_event_log import EventLog
|
from git_trace2_event_log import EventLog
|
||||||
from error import GitError, UploadError, DownloadError
|
from error import GitError, UploadError, DownloadError
|
||||||
from error import ManifestInvalidRevisionError, ManifestInvalidPathError
|
from error import ManifestInvalidRevisionError, ManifestInvalidPathError
|
||||||
@ -43,11 +46,22 @@ from repo_trace import IsTrace, Trace
|
|||||||
from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M, R_WORKTREE_M
|
from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M, R_WORKTREE_M
|
||||||
|
|
||||||
|
|
||||||
|
class SyncNetworkHalfResult(NamedTuple):
|
||||||
|
"""Sync_NetworkHalf return value."""
|
||||||
|
# True if successful.
|
||||||
|
success: bool
|
||||||
|
# Did we query the remote? False when optimized_fetch is True and we have the
|
||||||
|
# commit already present.
|
||||||
|
remote_fetched: bool
|
||||||
|
|
||||||
# Maximum sleep time allowed during retries.
|
# Maximum sleep time allowed during retries.
|
||||||
MAXIMUM_RETRY_SLEEP_SEC = 3600.0
|
MAXIMUM_RETRY_SLEEP_SEC = 3600.0
|
||||||
# +-10% random jitter is added to each Fetches retry sleep duration.
|
# +-10% random jitter is added to each Fetches retry sleep duration.
|
||||||
RETRY_JITTER_PERCENT = 0.1
|
RETRY_JITTER_PERCENT = 0.1
|
||||||
|
|
||||||
|
# Whether to use alternates.
|
||||||
|
# TODO(vapier): Remove knob once behavior is verified.
|
||||||
|
_ALTERNATES = os.environ.get('REPO_USE_ALTERNATES') == '1'
|
||||||
|
|
||||||
def _lwrite(path, content):
|
def _lwrite(path, content):
|
||||||
lock = '%s.lock' % path
|
lock = '%s.lock' % path
|
||||||
@ -200,6 +214,7 @@ class ReviewableBranch(object):
|
|||||||
private=False,
|
private=False,
|
||||||
notify=None,
|
notify=None,
|
||||||
wip=False,
|
wip=False,
|
||||||
|
ready=False,
|
||||||
dest_branch=None,
|
dest_branch=None,
|
||||||
validate_certs=True,
|
validate_certs=True,
|
||||||
push_options=None):
|
push_options=None):
|
||||||
@ -212,6 +227,7 @@ class ReviewableBranch(object):
|
|||||||
private=private,
|
private=private,
|
||||||
notify=notify,
|
notify=notify,
|
||||||
wip=wip,
|
wip=wip,
|
||||||
|
ready=ready,
|
||||||
dest_branch=dest_branch,
|
dest_branch=dest_branch,
|
||||||
validate_certs=validate_certs,
|
validate_certs=validate_certs,
|
||||||
push_options=push_options)
|
push_options=push_options)
|
||||||
@ -459,7 +475,13 @@ class RemoteSpec(object):
|
|||||||
|
|
||||||
class Project(object):
|
class Project(object):
|
||||||
# These objects can be shared between several working trees.
|
# These objects can be shared between several working trees.
|
||||||
shareable_dirs = ['hooks', 'objects', 'rr-cache']
|
@property
|
||||||
|
def shareable_dirs(self):
|
||||||
|
"""Return the shareable directories"""
|
||||||
|
if self.UseAlternates:
|
||||||
|
return ['hooks', 'rr-cache']
|
||||||
|
else:
|
||||||
|
return ['hooks', 'objects', 'rr-cache']
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
manifest,
|
manifest,
|
||||||
@ -589,6 +611,14 @@ class Project(object):
|
|||||||
self.bare_ref = GitRefs(self.gitdir)
|
self.bare_ref = GitRefs(self.gitdir)
|
||||||
self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=self.objdir)
|
self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=self.objdir)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def UseAlternates(self):
|
||||||
|
"""Whether git alternates are in use.
|
||||||
|
|
||||||
|
This will be removed once migration to alternates is complete.
|
||||||
|
"""
|
||||||
|
return _ALTERNATES or self.manifest.is_multimanifest
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def Derived(self):
|
def Derived(self):
|
||||||
return self.is_derived
|
return self.is_derived
|
||||||
@ -631,7 +661,7 @@ class Project(object):
|
|||||||
return True
|
return True
|
||||||
if self.work_git.DiffZ('diff-files'):
|
if self.work_git.DiffZ('diff-files'):
|
||||||
return True
|
return True
|
||||||
if consider_untracked and self.work_git.LsOthers():
|
if consider_untracked and self.UntrackedFiles():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -665,9 +695,13 @@ class Project(object):
|
|||||||
self._userident_name = ''
|
self._userident_name = ''
|
||||||
self._userident_email = ''
|
self._userident_email = ''
|
||||||
|
|
||||||
def GetRemote(self, name):
|
def GetRemote(self, name=None):
|
||||||
"""Get the configuration for a single remote.
|
"""Get the configuration for a single remote.
|
||||||
|
|
||||||
|
Defaults to the current project's remote.
|
||||||
"""
|
"""
|
||||||
|
if name is None:
|
||||||
|
name = self.remote.name
|
||||||
return self.config.GetRemote(name)
|
return self.config.GetRemote(name)
|
||||||
|
|
||||||
def GetBranch(self, name):
|
def GetBranch(self, name):
|
||||||
@ -714,7 +748,8 @@ class Project(object):
|
|||||||
The special manifest group "default" will match any project that
|
The special manifest group "default" will match any project that
|
||||||
does not have the special project group "notdefault"
|
does not have the special project group "notdefault"
|
||||||
"""
|
"""
|
||||||
expanded_manifest_groups = manifest_groups or ['default']
|
default_groups = self.manifest.default_groups or ['default']
|
||||||
|
expanded_manifest_groups = manifest_groups or default_groups
|
||||||
expanded_project_groups = ['all'] + (self.groups or [])
|
expanded_project_groups = ['all'] + (self.groups or [])
|
||||||
if 'notdefault' not in expanded_project_groups:
|
if 'notdefault' not in expanded_project_groups:
|
||||||
expanded_project_groups += ['default']
|
expanded_project_groups += ['default']
|
||||||
@ -759,33 +794,37 @@ class Project(object):
|
|||||||
if not get_all:
|
if not get_all:
|
||||||
return details
|
return details
|
||||||
|
|
||||||
changes = self.work_git.LsOthers()
|
changes = self.UntrackedFiles()
|
||||||
if changes:
|
if changes:
|
||||||
details.extend(changes)
|
details.extend(changes)
|
||||||
|
|
||||||
return details
|
return details
|
||||||
|
|
||||||
|
def UntrackedFiles(self):
|
||||||
|
"""Returns a list of strings, untracked files in the git tree."""
|
||||||
|
return self.work_git.LsOthers()
|
||||||
|
|
||||||
def HasChanges(self):
|
def HasChanges(self):
|
||||||
"""Returns true if there are uncommitted changes.
|
"""Returns true if there are uncommitted changes.
|
||||||
"""
|
"""
|
||||||
if self.UncommitedFiles(get_all=False):
|
return bool(self.UncommitedFiles(get_all=False))
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def PrintWorkTreeStatus(self, output_redir=None, quiet=False):
|
def PrintWorkTreeStatus(self, output_redir=None, quiet=False, local=False):
|
||||||
"""Prints the status of the repository to stdout.
|
"""Prints the status of the repository to stdout.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
output_redir: If specified, redirect the output to this object.
|
output_redir: If specified, redirect the output to this object.
|
||||||
quiet: If True then only print the project name. Do not print
|
quiet: If True then only print the project name. Do not print
|
||||||
the modified files, branch name, etc.
|
the modified files, branch name, etc.
|
||||||
|
local: a boolean, if True, the path is relative to the local
|
||||||
|
(sub)manifest. If false, the path is relative to the
|
||||||
|
outermost manifest.
|
||||||
"""
|
"""
|
||||||
if not platform_utils.isdir(self.worktree):
|
if not platform_utils.isdir(self.worktree):
|
||||||
if output_redir is None:
|
if output_redir is None:
|
||||||
output_redir = sys.stdout
|
output_redir = sys.stdout
|
||||||
print(file=output_redir)
|
print(file=output_redir)
|
||||||
print('project %s/' % self.relpath, file=output_redir)
|
print('project %s/' % self.RelPath(local), file=output_redir)
|
||||||
print(' missing (run "repo sync")', file=output_redir)
|
print(' missing (run "repo sync")', file=output_redir)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -803,7 +842,7 @@ class Project(object):
|
|||||||
out = StatusColoring(self.config)
|
out = StatusColoring(self.config)
|
||||||
if output_redir is not None:
|
if output_redir is not None:
|
||||||
out.redirect(output_redir)
|
out.redirect(output_redir)
|
||||||
out.project('project %-40s', self.relpath + '/ ')
|
out.project('project %-40s', self.RelPath(local) + '/ ')
|
||||||
|
|
||||||
if quiet:
|
if quiet:
|
||||||
out.nl()
|
out.nl()
|
||||||
@ -864,7 +903,8 @@ class Project(object):
|
|||||||
|
|
||||||
return 'DIRTY'
|
return 'DIRTY'
|
||||||
|
|
||||||
def PrintWorkTreeDiff(self, absolute_paths=False, output_redir=None):
|
def PrintWorkTreeDiff(self, absolute_paths=False, output_redir=None,
|
||||||
|
local=False):
|
||||||
"""Prints the status of the repository to stdout.
|
"""Prints the status of the repository to stdout.
|
||||||
"""
|
"""
|
||||||
out = DiffColoring(self.config)
|
out = DiffColoring(self.config)
|
||||||
@ -875,8 +915,8 @@ class Project(object):
|
|||||||
cmd.append('--color')
|
cmd.append('--color')
|
||||||
cmd.append(HEAD)
|
cmd.append(HEAD)
|
||||||
if absolute_paths:
|
if absolute_paths:
|
||||||
cmd.append('--src-prefix=a/%s/' % self.relpath)
|
cmd.append('--src-prefix=a/%s/' % self.RelPath(local))
|
||||||
cmd.append('--dst-prefix=b/%s/' % self.relpath)
|
cmd.append('--dst-prefix=b/%s/' % self.RelPath(local))
|
||||||
cmd.append('--')
|
cmd.append('--')
|
||||||
try:
|
try:
|
||||||
p = GitCommand(self,
|
p = GitCommand(self,
|
||||||
@ -886,14 +926,14 @@ class Project(object):
|
|||||||
p.Wait()
|
p.Wait()
|
||||||
except GitError as e:
|
except GitError as e:
|
||||||
out.nl()
|
out.nl()
|
||||||
out.project('project %s/' % self.relpath)
|
out.project('project %s/' % self.RelPath(local))
|
||||||
out.nl()
|
out.nl()
|
||||||
out.fail('%s', str(e))
|
out.fail('%s', str(e))
|
||||||
out.nl()
|
out.nl()
|
||||||
return False
|
return False
|
||||||
if p.stdout:
|
if p.stdout:
|
||||||
out.nl()
|
out.nl()
|
||||||
out.project('project %s/' % self.relpath)
|
out.project('project %s/' % self.RelPath(local))
|
||||||
out.nl()
|
out.nl()
|
||||||
out.write('%s', p.stdout)
|
out.write('%s', p.stdout)
|
||||||
return p.Wait() == 0
|
return p.Wait() == 0
|
||||||
@ -978,6 +1018,7 @@ class Project(object):
|
|||||||
private=False,
|
private=False,
|
||||||
notify=None,
|
notify=None,
|
||||||
wip=False,
|
wip=False,
|
||||||
|
ready=False,
|
||||||
dest_branch=None,
|
dest_branch=None,
|
||||||
validate_certs=True,
|
validate_certs=True,
|
||||||
push_options=None):
|
push_options=None):
|
||||||
@ -994,6 +1035,13 @@ class Project(object):
|
|||||||
if not branch.remote.review:
|
if not branch.remote.review:
|
||||||
raise GitError('remote %s has no review url' % branch.remote.name)
|
raise GitError('remote %s has no review url' % branch.remote.name)
|
||||||
|
|
||||||
|
# Basic validity check on label syntax.
|
||||||
|
for label in labels:
|
||||||
|
if not re.match(r'^.+[+-][0-9]+$', label):
|
||||||
|
raise UploadError(
|
||||||
|
f'invalid label syntax "{label}": labels use forms like '
|
||||||
|
'CodeReview+1 or Verified-1')
|
||||||
|
|
||||||
if dest_branch is None:
|
if dest_branch is None:
|
||||||
dest_branch = self.dest_branch
|
dest_branch = self.dest_branch
|
||||||
if dest_branch is None:
|
if dest_branch is None:
|
||||||
@ -1029,6 +1077,7 @@ class Project(object):
|
|||||||
if auto_topic:
|
if auto_topic:
|
||||||
opts += ['topic=' + branch.name]
|
opts += ['topic=' + branch.name]
|
||||||
opts += ['t=%s' % p for p in hashtags]
|
opts += ['t=%s' % p for p in hashtags]
|
||||||
|
# NB: No need to encode labels as they've been validated above.
|
||||||
opts += ['l=%s' % p for p in labels]
|
opts += ['l=%s' % p for p in labels]
|
||||||
|
|
||||||
opts += ['r=%s' % p for p in people[0]]
|
opts += ['r=%s' % p for p in people[0]]
|
||||||
@ -1039,6 +1088,8 @@ class Project(object):
|
|||||||
opts += ['private']
|
opts += ['private']
|
||||||
if wip:
|
if wip:
|
||||||
opts += ['wip']
|
opts += ['wip']
|
||||||
|
if ready:
|
||||||
|
opts += ['ready']
|
||||||
if opts:
|
if opts:
|
||||||
ref_spec = ref_spec + '%' + ','.join(opts)
|
ref_spec = ref_spec + '%' + ','.join(opts)
|
||||||
cmd.append(ref_spec)
|
cmd.append(ref_spec)
|
||||||
@ -1091,7 +1142,7 @@ class Project(object):
|
|||||||
if archive and not isinstance(self, MetaProject):
|
if archive and not isinstance(self, MetaProject):
|
||||||
if self.remote.url.startswith(('http://', 'https://')):
|
if self.remote.url.startswith(('http://', 'https://')):
|
||||||
_error("%s: Cannot fetch archives from http/https remotes.", self.name)
|
_error("%s: Cannot fetch archives from http/https remotes.", self.name)
|
||||||
return False
|
return SyncNetworkHalfResult(False, False)
|
||||||
|
|
||||||
name = self.relpath.replace('\\', '/')
|
name = self.relpath.replace('\\', '/')
|
||||||
name = name.replace('/', '_')
|
name = name.replace('/', '_')
|
||||||
@ -1102,19 +1153,19 @@ class Project(object):
|
|||||||
self._FetchArchive(tarpath, cwd=topdir)
|
self._FetchArchive(tarpath, cwd=topdir)
|
||||||
except GitError as e:
|
except GitError as e:
|
||||||
_error('%s', e)
|
_error('%s', e)
|
||||||
return False
|
return SyncNetworkHalfResult(False, False)
|
||||||
|
|
||||||
# From now on, we only need absolute tarpath
|
# From now on, we only need absolute tarpath
|
||||||
tarpath = os.path.join(topdir, tarpath)
|
tarpath = os.path.join(topdir, tarpath)
|
||||||
|
|
||||||
if not self._ExtractArchive(tarpath, path=topdir):
|
if not self._ExtractArchive(tarpath, path=topdir):
|
||||||
return False
|
return SyncNetworkHalfResult(False, True)
|
||||||
try:
|
try:
|
||||||
platform_utils.remove(tarpath)
|
platform_utils.remove(tarpath)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
_warn("Cannot remove archive %s: %s", tarpath, str(e))
|
_warn("Cannot remove archive %s: %s", tarpath, str(e))
|
||||||
self._CopyAndLinkFiles()
|
self._CopyAndLinkFiles()
|
||||||
return True
|
return SyncNetworkHalfResult(True, True)
|
||||||
|
|
||||||
# If the shared object dir already exists, don't try to rebootstrap with a
|
# If the shared object dir already exists, don't try to rebootstrap with a
|
||||||
# clone bundle download. We should have the majority of objects already.
|
# clone bundle download. We should have the majority of objects already.
|
||||||
@ -1133,6 +1184,17 @@ class Project(object):
|
|||||||
self._UpdateHooks(quiet=quiet)
|
self._UpdateHooks(quiet=quiet)
|
||||||
self._InitRemote()
|
self._InitRemote()
|
||||||
|
|
||||||
|
if self.UseAlternates:
|
||||||
|
# If gitdir/objects is a symlink, migrate it from the old layout.
|
||||||
|
gitdir_objects = os.path.join(self.gitdir, 'objects')
|
||||||
|
if platform_utils.islink(gitdir_objects):
|
||||||
|
platform_utils.remove(gitdir_objects, missing_ok=True)
|
||||||
|
gitdir_alt = os.path.join(self.gitdir, 'objects/info/alternates')
|
||||||
|
if not os.path.exists(gitdir_alt):
|
||||||
|
os.makedirs(os.path.dirname(gitdir_alt), exist_ok=True)
|
||||||
|
_lwrite(gitdir_alt, os.path.join(
|
||||||
|
os.path.relpath(self.objdir, gitdir_objects), 'objects') + '\n')
|
||||||
|
|
||||||
if is_new:
|
if is_new:
|
||||||
alt = os.path.join(self.objdir, 'objects/info/alternates')
|
alt = os.path.join(self.objdir, 'objects/info/alternates')
|
||||||
try:
|
try:
|
||||||
@ -1167,9 +1229,11 @@ class Project(object):
|
|||||||
depth = self.manifest.manifestProject.depth
|
depth = self.manifest.manifestProject.depth
|
||||||
|
|
||||||
# See if we can skip the network fetch entirely.
|
# See if we can skip the network fetch entirely.
|
||||||
|
remote_fetched = False
|
||||||
if not (optimized_fetch and
|
if not (optimized_fetch and
|
||||||
(ID_RE.match(self.revisionExpr) and
|
(ID_RE.match(self.revisionExpr) and
|
||||||
self._CheckForImmutableRevision())):
|
self._CheckForImmutableRevision())):
|
||||||
|
remote_fetched = True
|
||||||
if not self._RemoteFetch(
|
if not self._RemoteFetch(
|
||||||
initial=is_new,
|
initial=is_new,
|
||||||
quiet=quiet, verbose=verbose, output_redir=output_redir,
|
quiet=quiet, verbose=verbose, output_redir=output_redir,
|
||||||
@ -1178,7 +1242,7 @@ class Project(object):
|
|||||||
submodules=submodules, force_sync=force_sync,
|
submodules=submodules, force_sync=force_sync,
|
||||||
ssh_proxy=ssh_proxy,
|
ssh_proxy=ssh_proxy,
|
||||||
clone_filter=clone_filter, retry_fetches=retry_fetches):
|
clone_filter=clone_filter, retry_fetches=retry_fetches):
|
||||||
return False
|
return SyncNetworkHalfResult(False, remote_fetched)
|
||||||
|
|
||||||
mp = self.manifest.manifestProject
|
mp = self.manifest.manifestProject
|
||||||
dissociate = mp.dissociate
|
dissociate = mp.dissociate
|
||||||
@ -1191,7 +1255,7 @@ class Project(object):
|
|||||||
if p.stdout and output_redir:
|
if p.stdout and output_redir:
|
||||||
output_redir.write(p.stdout)
|
output_redir.write(p.stdout)
|
||||||
if p.Wait() != 0:
|
if p.Wait() != 0:
|
||||||
return False
|
return SyncNetworkHalfResult(False, remote_fetched)
|
||||||
platform_utils.remove(alternates_file)
|
platform_utils.remove(alternates_file)
|
||||||
|
|
||||||
if self.worktree:
|
if self.worktree:
|
||||||
@ -1200,7 +1264,7 @@ class Project(object):
|
|||||||
self._InitMirrorHead()
|
self._InitMirrorHead()
|
||||||
platform_utils.remove(os.path.join(self.gitdir, 'FETCH_HEAD'),
|
platform_utils.remove(os.path.join(self.gitdir, 'FETCH_HEAD'),
|
||||||
missing_ok=True)
|
missing_ok=True)
|
||||||
return True
|
return SyncNetworkHalfResult(True, remote_fetched)
|
||||||
|
|
||||||
def PostRepoUpgrade(self):
|
def PostRepoUpgrade(self):
|
||||||
self._InitHooks()
|
self._InitHooks()
|
||||||
@ -1233,7 +1297,7 @@ class Project(object):
|
|||||||
if self.revisionId:
|
if self.revisionId:
|
||||||
return self.revisionId
|
return self.revisionId
|
||||||
|
|
||||||
rem = self.GetRemote(self.remote.name)
|
rem = self.GetRemote()
|
||||||
rev = rem.ToLocal(self.revisionExpr)
|
rev = rem.ToLocal(self.revisionExpr)
|
||||||
|
|
||||||
if all_refs is not None and rev in all_refs:
|
if all_refs is not None and rev in all_refs:
|
||||||
@ -1398,6 +1462,8 @@ class Project(object):
|
|||||||
cnt_mine += 1
|
cnt_mine += 1
|
||||||
|
|
||||||
if not upstream_gain and cnt_mine == len(local_changes):
|
if not upstream_gain and cnt_mine == len(local_changes):
|
||||||
|
# The copy/linkfile config may have changed.
|
||||||
|
self._CopyAndLinkFiles()
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.IsDirty(consider_untracked=False):
|
if self.IsDirty(consider_untracked=False):
|
||||||
@ -1425,7 +1491,7 @@ class Project(object):
|
|||||||
"discarding %d commits removed from upstream",
|
"discarding %d commits removed from upstream",
|
||||||
len(local_changes) - cnt_mine)
|
len(local_changes) - cnt_mine)
|
||||||
|
|
||||||
branch.remote = self.GetRemote(self.remote.name)
|
branch.remote = self.GetRemote()
|
||||||
if not ID_RE.match(self.revisionExpr):
|
if not ID_RE.match(self.revisionExpr):
|
||||||
# in case of manifest sync the revisionExpr might be a SHA1
|
# in case of manifest sync the revisionExpr might be a SHA1
|
||||||
branch.merge = self.revisionExpr
|
branch.merge = self.revisionExpr
|
||||||
@ -1483,7 +1549,7 @@ class Project(object):
|
|||||||
def DownloadPatchSet(self, change_id, patch_id):
|
def DownloadPatchSet(self, change_id, patch_id):
|
||||||
"""Download a single patch set of a single change to FETCH_HEAD.
|
"""Download a single patch set of a single change to FETCH_HEAD.
|
||||||
"""
|
"""
|
||||||
remote = self.GetRemote(self.remote.name)
|
remote = self.GetRemote()
|
||||||
|
|
||||||
cmd = ['fetch', remote.name]
|
cmd = ['fetch', remote.name]
|
||||||
cmd.append('refs/changes/%2.2d/%d/%d'
|
cmd.append('refs/changes/%2.2d/%d/%d'
|
||||||
@ -1513,14 +1579,14 @@ class Project(object):
|
|||||||
if self.IsDirty():
|
if self.IsDirty():
|
||||||
if force:
|
if force:
|
||||||
print('warning: %s: Removing dirty project: uncommitted changes lost.' %
|
print('warning: %s: Removing dirty project: uncommitted changes lost.' %
|
||||||
(self.relpath,), file=sys.stderr)
|
(self.RelPath(local=False),), file=sys.stderr)
|
||||||
else:
|
else:
|
||||||
print('error: %s: Cannot remove project: uncommitted changes are '
|
print('error: %s: Cannot remove project: uncommitted changes are '
|
||||||
'present.\n' % (self.relpath,), file=sys.stderr)
|
'present.\n' % (self.RelPath(local=False),), file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not quiet:
|
if not quiet:
|
||||||
print('%s: Deleting obsolete checkout.' % (self.relpath,))
|
print('%s: Deleting obsolete checkout.' % (self.RelPath(local=False),))
|
||||||
|
|
||||||
# Unlock and delink from the main worktree. We don't use git's worktree
|
# Unlock and delink from the main worktree. We don't use git's worktree
|
||||||
# remove because it will recursively delete projects -- we handle that
|
# remove because it will recursively delete projects -- we handle that
|
||||||
@ -1559,7 +1625,8 @@ class Project(object):
|
|||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
print('error: %s: %s' % (self.gitdir, e), file=sys.stderr)
|
print('error: %s: %s' % (self.gitdir, e), file=sys.stderr)
|
||||||
print('error: %s: Failed to delete obsolete checkout; remove manually, '
|
print('error: %s: Failed to delete obsolete checkout; remove manually, '
|
||||||
'then run `repo sync -l`.' % (self.relpath,), file=sys.stderr)
|
'then run `repo sync -l`.' % (self.RelPath(local=False),),
|
||||||
|
file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Delete everything under the worktree, except for directories that contain
|
# Delete everything under the worktree, except for directories that contain
|
||||||
@ -1595,7 +1662,7 @@ class Project(object):
|
|||||||
print('error: %s: Failed to remove: %s' % (d, e), file=sys.stderr)
|
print('error: %s: Failed to remove: %s' % (d, e), file=sys.stderr)
|
||||||
failed = True
|
failed = True
|
||||||
if failed:
|
if failed:
|
||||||
print('error: %s: Failed to delete obsolete checkout.' % (self.relpath,),
|
print('error: %s: Failed to delete obsolete checkout.' % (self.RelPath(local=False),),
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
print(' Remove manually, then run `repo sync -l`.', file=sys.stderr)
|
print(' Remove manually, then run `repo sync -l`.', file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
@ -1624,13 +1691,10 @@ class Project(object):
|
|||||||
|
|
||||||
all_refs = self.bare_ref.all
|
all_refs = self.bare_ref.all
|
||||||
if R_HEADS + name in all_refs:
|
if R_HEADS + name in all_refs:
|
||||||
return GitCommand(self,
|
return GitCommand(self, ['checkout', '-q', name, '--']).Wait() == 0
|
||||||
['checkout', name, '--'],
|
|
||||||
capture_stdout=True,
|
|
||||||
capture_stderr=True).Wait() == 0
|
|
||||||
|
|
||||||
branch = self.GetBranch(name)
|
branch = self.GetBranch(name)
|
||||||
branch.remote = self.GetRemote(self.remote.name)
|
branch.remote = self.GetRemote()
|
||||||
branch.merge = branch_merge
|
branch.merge = branch_merge
|
||||||
if not branch.merge.startswith('refs/') and not ID_RE.match(branch_merge):
|
if not branch.merge.startswith('refs/') and not ID_RE.match(branch_merge):
|
||||||
branch.merge = R_HEADS + branch_merge
|
branch.merge = R_HEADS + branch_merge
|
||||||
@ -1652,10 +1716,7 @@ class Project(object):
|
|||||||
branch.Save()
|
branch.Save()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if GitCommand(self,
|
if GitCommand(self, ['checkout', '-q', '-b', branch.name, revid]).Wait() == 0:
|
||||||
['checkout', '-b', branch.name, revid],
|
|
||||||
capture_stdout=True,
|
|
||||||
capture_stderr=True).Wait() == 0:
|
|
||||||
branch.Save()
|
branch.Save()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -1998,7 +2059,7 @@ class Project(object):
|
|||||||
self.bare_git.rev_list('-1', '--missing=allow-any',
|
self.bare_git.rev_list('-1', '--missing=allow-any',
|
||||||
'%s^0' % self.revisionExpr, '--')
|
'%s^0' % self.revisionExpr, '--')
|
||||||
if self.upstream:
|
if self.upstream:
|
||||||
rev = self.GetRemote(self.remote.name).ToLocal(self.upstream)
|
rev = self.GetRemote().ToLocal(self.upstream)
|
||||||
self.bare_git.rev_list('-1', '--missing=allow-any',
|
self.bare_git.rev_list('-1', '--missing=allow-any',
|
||||||
'%s^0' % rev, '--')
|
'%s^0' % rev, '--')
|
||||||
self.bare_git.merge_base('--is-ancestor', self.revisionExpr, rev)
|
self.bare_git.merge_base('--is-ancestor', self.revisionExpr, rev)
|
||||||
@ -2010,7 +2071,7 @@ class Project(object):
|
|||||||
def _FetchArchive(self, tarpath, cwd=None):
|
def _FetchArchive(self, tarpath, cwd=None):
|
||||||
cmd = ['archive', '-v', '-o', tarpath]
|
cmd = ['archive', '-v', '-o', tarpath]
|
||||||
cmd.append('--remote=%s' % self.remote.url)
|
cmd.append('--remote=%s' % self.remote.url)
|
||||||
cmd.append('--prefix=%s/' % self.relpath)
|
cmd.append('--prefix=%s/' % self.RelPath(local=False))
|
||||||
cmd.append(self.revisionExpr)
|
cmd.append(self.revisionExpr)
|
||||||
|
|
||||||
command = GitCommand(self, cmd, cwd=cwd,
|
command = GitCommand(self, cmd, cwd=cwd,
|
||||||
@ -2156,6 +2217,8 @@ class Project(object):
|
|||||||
if prune:
|
if prune:
|
||||||
cmd.append('--prune')
|
cmd.append('--prune')
|
||||||
|
|
||||||
|
# Always pass something for --recurse-submodules, git with GIT_DIR behaves
|
||||||
|
# incorrectly when not given `--recurse-submodules=no`. (b/218891912)
|
||||||
cmd.append(f'--recurse-submodules={"on-demand" if submodules else "no"}')
|
cmd.append(f'--recurse-submodules={"on-demand" if submodules else "no"}')
|
||||||
|
|
||||||
spec = []
|
spec = []
|
||||||
@ -2287,7 +2350,7 @@ class Project(object):
|
|||||||
if initial and (self.manifest.manifestProject.depth or self.clone_depth):
|
if initial and (self.manifest.manifestProject.depth or self.clone_depth):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
remote = self.GetRemote(self.remote.name)
|
remote = self.GetRemote()
|
||||||
bundle_url = remote.url + '/clone.bundle'
|
bundle_url = remote.url + '/clone.bundle'
|
||||||
bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
|
bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
|
||||||
if GetSchemeFromUrl(bundle_url) not in ('http', 'https',
|
if GetSchemeFromUrl(bundle_url) not in ('http', 'https',
|
||||||
@ -2592,7 +2655,7 @@ class Project(object):
|
|||||||
if not filecmp.cmp(stock_hook, dst, shallow=False):
|
if not filecmp.cmp(stock_hook, dst, shallow=False):
|
||||||
if not quiet:
|
if not quiet:
|
||||||
_warn("%s: Not replacing locally modified %s hook",
|
_warn("%s: Not replacing locally modified %s hook",
|
||||||
self.relpath, name)
|
self.RelPath(local=False), name)
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
platform_utils.symlink(
|
platform_utils.symlink(
|
||||||
@ -2608,7 +2671,7 @@ class Project(object):
|
|||||||
|
|
||||||
def _InitRemote(self):
|
def _InitRemote(self):
|
||||||
if self.remote.url:
|
if self.remote.url:
|
||||||
remote = self.GetRemote(self.remote.name)
|
remote = self.GetRemote()
|
||||||
remote.url = self.remote.url
|
remote.url = self.remote.url
|
||||||
remote.pushUrl = self.remote.pushUrl
|
remote.pushUrl = self.remote.pushUrl
|
||||||
remote.review = self.remote.review
|
remote.review = self.remote.review
|
||||||
@ -2621,6 +2684,7 @@ class Project(object):
|
|||||||
remote.Save()
|
remote.Save()
|
||||||
|
|
||||||
def _InitMRef(self):
|
def _InitMRef(self):
|
||||||
|
"""Initialize the pseudo m/<manifest branch> ref."""
|
||||||
if self.manifest.branch:
|
if self.manifest.branch:
|
||||||
if self.use_git_worktrees:
|
if self.use_git_worktrees:
|
||||||
# Set up the m/ space to point to the worktree-specific ref space.
|
# Set up the m/ space to point to the worktree-specific ref space.
|
||||||
@ -2650,6 +2714,16 @@ class Project(object):
|
|||||||
self._InitAnyMRef(HEAD, self.bare_git)
|
self._InitAnyMRef(HEAD, self.bare_git)
|
||||||
|
|
||||||
def _InitAnyMRef(self, ref, active_git, detach=False):
|
def _InitAnyMRef(self, ref, active_git, detach=False):
|
||||||
|
"""Initialize |ref| in |active_git| to the value in the manifest.
|
||||||
|
|
||||||
|
This points |ref| to the <project> setting in the manifest.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ref: The branch to update.
|
||||||
|
active_git: The git repository to make updates in.
|
||||||
|
detach: Whether to update target of symbolic refs, or overwrite the ref
|
||||||
|
directly (and thus make it non-symbolic).
|
||||||
|
"""
|
||||||
cur = self.bare_ref.symref(ref)
|
cur = self.bare_ref.symref(ref)
|
||||||
|
|
||||||
if self.revisionId:
|
if self.revisionId:
|
||||||
@ -2658,7 +2732,7 @@ class Project(object):
|
|||||||
dst = self.revisionId + '^0'
|
dst = self.revisionId + '^0'
|
||||||
active_git.UpdateRef(ref, dst, message=msg, detach=True)
|
active_git.UpdateRef(ref, dst, message=msg, detach=True)
|
||||||
else:
|
else:
|
||||||
remote = self.GetRemote(self.remote.name)
|
remote = self.GetRemote()
|
||||||
dst = remote.ToLocal(self.revisionExpr)
|
dst = remote.ToLocal(self.revisionExpr)
|
||||||
if cur != dst:
|
if cur != dst:
|
||||||
msg = 'manifest set to %s' % self.revisionExpr
|
msg = 'manifest set to %s' % self.revisionExpr
|
||||||
@ -2687,7 +2761,7 @@ class Project(object):
|
|||||||
'work tree. If you\'re comfortable with the '
|
'work tree. If you\'re comfortable with the '
|
||||||
'possibility of losing the work tree\'s git metadata,'
|
'possibility of losing the work tree\'s git metadata,'
|
||||||
' use `repo sync --force-sync {0}` to '
|
' use `repo sync --force-sync {0}` to '
|
||||||
'proceed.'.format(self.relpath))
|
'proceed.'.format(self.RelPath(local=False)))
|
||||||
|
|
||||||
def _ReferenceGitDir(self, gitdir, dotgit, copy_all):
|
def _ReferenceGitDir(self, gitdir, dotgit, copy_all):
|
||||||
"""Update |dotgit| to reference |gitdir|, using symlinks where possible.
|
"""Update |dotgit| to reference |gitdir|, using symlinks where possible.
|
||||||
@ -3167,7 +3241,7 @@ class _InfoMessage(object):
|
|||||||
self.text = text
|
self.text = text
|
||||||
|
|
||||||
def Print(self, syncbuf):
|
def Print(self, syncbuf):
|
||||||
syncbuf.out.info('%s/: %s', self.project.relpath, self.text)
|
syncbuf.out.info('%s/: %s', self.project.RelPath(local=False), self.text)
|
||||||
syncbuf.out.nl()
|
syncbuf.out.nl()
|
||||||
|
|
||||||
|
|
||||||
@ -3179,7 +3253,7 @@ class _Failure(object):
|
|||||||
|
|
||||||
def Print(self, syncbuf):
|
def Print(self, syncbuf):
|
||||||
syncbuf.out.fail('error: %s/: %s',
|
syncbuf.out.fail('error: %s/: %s',
|
||||||
self.project.relpath,
|
self.project.RelPath(local=False),
|
||||||
str(self.why))
|
str(self.why))
|
||||||
syncbuf.out.nl()
|
syncbuf.out.nl()
|
||||||
|
|
||||||
@ -3192,7 +3266,7 @@ class _Later(object):
|
|||||||
|
|
||||||
def Run(self, syncbuf):
|
def Run(self, syncbuf):
|
||||||
out = syncbuf.out
|
out = syncbuf.out
|
||||||
out.project('project %s/', self.project.relpath)
|
out.project('project %s/', self.project.RelPath(local=False))
|
||||||
out.nl()
|
out.nl()
|
||||||
try:
|
try:
|
||||||
self.action()
|
self.action()
|
||||||
@ -3371,73 +3445,139 @@ class ManifestProject(MetaProject):
|
|||||||
@property
|
@property
|
||||||
def reference(self):
|
def reference(self):
|
||||||
"""The --reference for this manifest."""
|
"""The --reference for this manifest."""
|
||||||
self.config.GetString('repo.reference')
|
return self.config.GetString('repo.reference')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def dissociate(self):
|
def dissociate(self):
|
||||||
"""Whether to dissociate."""
|
"""Whether to dissociate."""
|
||||||
self.config.GetBoolean('repo.dissociate')
|
return self.config.GetBoolean('repo.dissociate')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def archive(self):
|
def archive(self):
|
||||||
"""Whether we use archive."""
|
"""Whether we use archive."""
|
||||||
self.config.GetBoolean('repo.archive')
|
return self.config.GetBoolean('repo.archive')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mirror(self):
|
def mirror(self):
|
||||||
"""Whether we use mirror."""
|
"""Whether we use mirror."""
|
||||||
self.config.GetBoolean('repo.mirror')
|
return self.config.GetBoolean('repo.mirror')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def use_worktree(self):
|
def use_worktree(self):
|
||||||
"""Whether we use worktree."""
|
"""Whether we use worktree."""
|
||||||
self.config.GetBoolean('repo.worktree')
|
return self.config.GetBoolean('repo.worktree')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clone_bundle(self):
|
def clone_bundle(self):
|
||||||
"""Whether we use clone_bundle."""
|
"""Whether we use clone_bundle."""
|
||||||
self.config.GetBoolean('repo.clonebundle')
|
return self.config.GetBoolean('repo.clonebundle')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def submodules(self):
|
def submodules(self):
|
||||||
"""Whether we use submodules."""
|
"""Whether we use submodules."""
|
||||||
self.config.GetBoolean('repo.submodules')
|
return self.config.GetBoolean('repo.submodules')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def git_lfs(self):
|
def git_lfs(self):
|
||||||
"""Whether we use git_lfs."""
|
"""Whether we use git_lfs."""
|
||||||
self.config.GetBoolean('repo.git-lfs')
|
return self.config.GetBoolean('repo.git-lfs')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def use_superproject(self):
|
def use_superproject(self):
|
||||||
"""Whether we use superproject."""
|
"""Whether we use superproject."""
|
||||||
self.config.GetBoolean('repo.superproject')
|
return self.config.GetBoolean('repo.superproject')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def partial_clone(self):
|
def partial_clone(self):
|
||||||
"""Whether this is a partial clone."""
|
"""Whether this is a partial clone."""
|
||||||
self.config.GetBoolean('repo.partialclone')
|
return self.config.GetBoolean('repo.partialclone')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def depth(self):
|
def depth(self):
|
||||||
"""Partial clone depth."""
|
"""Partial clone depth."""
|
||||||
self.config.GetString('repo.depth')
|
return self.config.GetString('repo.depth')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clone_filter(self):
|
def clone_filter(self):
|
||||||
"""The clone filter."""
|
"""The clone filter."""
|
||||||
self.config.GetString('repo.clonefilter')
|
return self.config.GetString('repo.clonefilter')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def partial_clone_exclude(self):
|
def partial_clone_exclude(self):
|
||||||
"""Partial clone exclude string"""
|
"""Partial clone exclude string"""
|
||||||
self.config.GetBoolean('repo.partialcloneexclude')
|
return self.config.GetBoolean('repo.partialcloneexclude')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def manifest_platform(self):
|
||||||
|
"""The --platform argument from `repo init`."""
|
||||||
|
return self.config.GetString('manifest.platform')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _platform_name(self):
|
def _platform_name(self):
|
||||||
"""Return the name of the platform."""
|
"""Return the name of the platform."""
|
||||||
return platform.system().lower()
|
return platform.system().lower()
|
||||||
|
|
||||||
|
def SyncWithPossibleInit(self, submanifest, verbose=False,
|
||||||
|
current_branch_only=False, tags='', git_event_log=None):
|
||||||
|
"""Sync a manifestProject, possibly for the first time.
|
||||||
|
|
||||||
|
Call Sync() with arguments from the most recent `repo init`. If this is a
|
||||||
|
new sub manifest, then inherit options from the parent's manifestProject.
|
||||||
|
|
||||||
|
This is used by subcmds.Sync() to do an initial download of new sub
|
||||||
|
manifests.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
submanifest: an XmlSubmanifest, the submanifest to re-sync.
|
||||||
|
verbose: a boolean, whether to show all output, rather than only errors.
|
||||||
|
current_branch_only: a boolean, whether to only fetch the current manifest
|
||||||
|
branch from the server.
|
||||||
|
tags: a boolean, whether to fetch tags.
|
||||||
|
git_event_log: an EventLog, for git tracing.
|
||||||
|
"""
|
||||||
|
# TODO(lamontjones): when refactoring sync (and init?) consider how to
|
||||||
|
# better get the init options that we should use for new submanifests that
|
||||||
|
# are added when syncing an existing workspace.
|
||||||
|
git_event_log = git_event_log or EventLog()
|
||||||
|
spec = submanifest.ToSubmanifestSpec()
|
||||||
|
# Use the init options from the existing manifestProject, or the parent if
|
||||||
|
# it doesn't exist.
|
||||||
|
#
|
||||||
|
# Today, we only support changing manifest_groups on the sub-manifest, with
|
||||||
|
# no supported-for-the-user way to change the other arguments from those
|
||||||
|
# specified by the outermost manifest.
|
||||||
|
#
|
||||||
|
# TODO(lamontjones): determine which of these should come from the outermost
|
||||||
|
# manifest and which should come from the parent manifest.
|
||||||
|
mp = self if self.Exists else submanifest.parent.manifestProject
|
||||||
|
return self.Sync(
|
||||||
|
manifest_url=spec.manifestUrl,
|
||||||
|
manifest_branch=spec.revision,
|
||||||
|
standalone_manifest=mp.standalone_manifest_url,
|
||||||
|
groups=mp.manifest_groups,
|
||||||
|
platform=mp.manifest_platform,
|
||||||
|
mirror=mp.mirror,
|
||||||
|
dissociate=mp.dissociate,
|
||||||
|
reference=mp.reference,
|
||||||
|
worktree=mp.use_worktree,
|
||||||
|
submodules=mp.submodules,
|
||||||
|
archive=mp.archive,
|
||||||
|
partial_clone=mp.partial_clone,
|
||||||
|
clone_filter=mp.clone_filter,
|
||||||
|
partial_clone_exclude=mp.partial_clone_exclude,
|
||||||
|
clone_bundle=mp.clone_bundle,
|
||||||
|
git_lfs=mp.git_lfs,
|
||||||
|
use_superproject=mp.use_superproject,
|
||||||
|
verbose=verbose,
|
||||||
|
current_branch_only=current_branch_only,
|
||||||
|
tags=tags,
|
||||||
|
depth=mp.depth,
|
||||||
|
git_event_log=git_event_log,
|
||||||
|
manifest_name=spec.manifestName,
|
||||||
|
this_manifest_only=True,
|
||||||
|
outer_manifest=False,
|
||||||
|
)
|
||||||
|
|
||||||
def Sync(self, _kwargs_only=(), manifest_url='', manifest_branch=None,
|
def Sync(self, _kwargs_only=(), manifest_url='', manifest_branch=None,
|
||||||
standalone_manifest=False, groups='', mirror=False, reference='',
|
standalone_manifest=False, groups='', mirror=False, reference='',
|
||||||
dissociate=False, worktree=False, submodules=False, archive=False,
|
dissociate=False, worktree=False, submodules=False, archive=False,
|
||||||
@ -3479,7 +3619,7 @@ class ManifestProject(MetaProject):
|
|||||||
platform: a string, restrict the checkout to projects with the specified
|
platform: a string, restrict the checkout to projects with the specified
|
||||||
platform group.
|
platform group.
|
||||||
git_event_log: an EventLog, for git tracing.
|
git_event_log: an EventLog, for git tracing.
|
||||||
tags: a boolean, whether to fetch tags.,
|
tags: a boolean, whether to fetch tags.
|
||||||
manifest_name: a string, the name of the manifest file to use.
|
manifest_name: a string, the name of the manifest file to use.
|
||||||
this_manifest_only: a boolean, whether to only operate on the current sub
|
this_manifest_only: a boolean, whether to only operate on the current sub
|
||||||
manifest.
|
manifest.
|
||||||
@ -3490,7 +3630,7 @@ class ManifestProject(MetaProject):
|
|||||||
"""
|
"""
|
||||||
assert _kwargs_only == (), 'Sync only accepts keyword arguments.'
|
assert _kwargs_only == (), 'Sync only accepts keyword arguments.'
|
||||||
|
|
||||||
groups = groups or 'default'
|
groups = groups or self.manifest.GetDefaultGroupsStr(with_platform=False)
|
||||||
platform = platform or 'auto'
|
platform = platform or 'auto'
|
||||||
git_event_log = git_event_log or EventLog()
|
git_event_log = git_event_log or EventLog()
|
||||||
if outer_manifest and self.manifest.is_submanifest:
|
if outer_manifest and self.manifest.is_submanifest:
|
||||||
@ -3584,7 +3724,7 @@ class ManifestProject(MetaProject):
|
|||||||
|
|
||||||
# Set the remote URL before the remote branch as we might need it below.
|
# Set the remote URL before the remote branch as we might need it below.
|
||||||
if manifest_url:
|
if manifest_url:
|
||||||
r = self.GetRemote(self.remote.name)
|
r = self.GetRemote()
|
||||||
r.url = manifest_url
|
r.url = manifest_url
|
||||||
r.ResetFetch()
|
r.ResetFetch()
|
||||||
r.Save()
|
r.Save()
|
||||||
@ -3620,6 +3760,7 @@ class ManifestProject(MetaProject):
|
|||||||
elif platform != 'none':
|
elif platform != 'none':
|
||||||
print('fatal: invalid platform flag', file=sys.stderr)
|
print('fatal: invalid platform flag', file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
self.config.SetString('manifest.platform', platform)
|
||||||
|
|
||||||
groups = [x for x in groups if x]
|
groups = [x for x in groups if x]
|
||||||
groupstr = ','.join(groups)
|
groupstr = ','.join(groups)
|
||||||
@ -3703,23 +3844,13 @@ class ManifestProject(MetaProject):
|
|||||||
if use_superproject is not None:
|
if use_superproject is not None:
|
||||||
self.config.SetBoolean('repo.superproject', use_superproject)
|
self.config.SetBoolean('repo.superproject', use_superproject)
|
||||||
|
|
||||||
if standalone_manifest:
|
if not standalone_manifest:
|
||||||
if is_new:
|
if not self.Sync_NetworkHalf(
|
||||||
manifest_name = 'default.xml'
|
is_new=is_new, quiet=not verbose, verbose=verbose,
|
||||||
manifest_data = fetch.fetch_file(manifest_url, verbose=verbose)
|
clone_bundle=clone_bundle, current_branch_only=current_branch_only,
|
||||||
dest = os.path.join(self.worktree, manifest_name)
|
tags=tags, submodules=submodules, clone_filter=clone_filter,
|
||||||
os.makedirs(os.path.dirname(dest), exist_ok=True)
|
partial_clone_exclude=self.manifest.PartialCloneExclude).success:
|
||||||
with open(dest, 'wb') as f:
|
r = self.GetRemote()
|
||||||
f.write(manifest_data)
|
|
||||||
return
|
|
||||||
|
|
||||||
if not self.Sync_NetworkHalf(is_new=is_new, quiet=not verbose, verbose=verbose,
|
|
||||||
clone_bundle=clone_bundle,
|
|
||||||
current_branch_only=current_branch_only,
|
|
||||||
tags=tags, submodules=submodules,
|
|
||||||
clone_filter=clone_filter,
|
|
||||||
partial_clone_exclude=self.manifest.PartialCloneExclude):
|
|
||||||
r = self.GetRemote(self.remote.name)
|
|
||||||
print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr)
|
print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr)
|
||||||
|
|
||||||
# Better delete the manifest git dir if we created it; otherwise next
|
# Better delete the manifest git dir if we created it; otherwise next
|
||||||
@ -3744,6 +3875,15 @@ class ManifestProject(MetaProject):
|
|||||||
print('fatal: manifest name (-m) is required.', file=sys.stderr)
|
print('fatal: manifest name (-m) is required.', file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
elif is_new:
|
||||||
|
# This is a new standalone manifest.
|
||||||
|
manifest_name = 'default.xml'
|
||||||
|
manifest_data = fetch.fetch_file(manifest_url, verbose=verbose)
|
||||||
|
dest = os.path.join(self.worktree, manifest_name)
|
||||||
|
os.makedirs(os.path.dirname(dest), exist_ok=True)
|
||||||
|
with open(dest, 'wb') as f:
|
||||||
|
f.write(manifest_data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.manifest.Link(manifest_name)
|
self.manifest.Link(manifest_name)
|
||||||
except ManifestParseError as e:
|
except ManifestParseError as e:
|
||||||
@ -3754,7 +3894,7 @@ class ManifestProject(MetaProject):
|
|||||||
|
|
||||||
if not this_manifest_only:
|
if not this_manifest_only:
|
||||||
for submanifest in self.manifest.submanifests.values():
|
for submanifest in self.manifest.submanifests.values():
|
||||||
spec = submanifest.ToSubmanifestSpec(root=self.manifest.outer_client)
|
spec = submanifest.ToSubmanifestSpec()
|
||||||
submanifest.repo_client.manifestProject.Sync(
|
submanifest.repo_client.manifestProject.Sync(
|
||||||
manifest_url=spec.manifestUrl,
|
manifest_url=spec.manifestUrl,
|
||||||
manifest_branch=spec.revision,
|
manifest_branch=spec.revision,
|
||||||
@ -3783,10 +3923,10 @@ class ManifestProject(MetaProject):
|
|||||||
outer_manifest=False,
|
outer_manifest=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Lastly, clone the superproject(s).
|
# Lastly, if the manifest has a <superproject> then have the superproject
|
||||||
if self.manifest.manifestProject.use_superproject:
|
# sync it (if it will be used).
|
||||||
sync_result = Superproject(
|
if git_superproject.UseSuperproject(use_superproject, self.manifest):
|
||||||
self.manifest, self.manifest.repodir, git_event_log, quiet=not verbose).Sync()
|
sync_result = self.manifest.superproject.Sync(git_event_log)
|
||||||
if not sync_result.success:
|
if not sync_result.success:
|
||||||
print('warning: git update of superproject for '
|
print('warning: git update of superproject for '
|
||||||
f'{self.manifest.path_prefix} failed, repo sync will not use '
|
f'{self.manifest.path_prefix} failed, repo sync will not use '
|
||||||
|
@ -59,18 +59,26 @@ def main(argv):
|
|||||||
version = RepoSourceVersion()
|
version = RepoSourceVersion()
|
||||||
cmdlist = [['help2man', '-N', '-n', f'repo {cmd} - manual page for repo {cmd}',
|
cmdlist = [['help2man', '-N', '-n', f'repo {cmd} - manual page for repo {cmd}',
|
||||||
'-S', f'repo {cmd}', '-m', 'Repo Manual', f'--version-string={version}',
|
'-S', f'repo {cmd}', '-m', 'Repo Manual', f'--version-string={version}',
|
||||||
'-o', MANDIR.joinpath(f'repo-{cmd}.1.tmp'), TOPDIR.joinpath('repo'),
|
'-o', MANDIR.joinpath(f'repo-{cmd}.1.tmp'), './repo',
|
||||||
'-h', f'help {cmd}'] for cmd in subcmds.all_commands]
|
'-h', f'help {cmd}'] for cmd in subcmds.all_commands]
|
||||||
cmdlist.append(['help2man', '-N', '-n', 'repository management tool built on top of git',
|
cmdlist.append(['help2man', '-N', '-n', 'repository management tool built on top of git',
|
||||||
'-S', 'repo', '-m', 'Repo Manual', f'--version-string={version}',
|
'-S', 'repo', '-m', 'Repo Manual', f'--version-string={version}',
|
||||||
'-o', MANDIR.joinpath('repo.1.tmp'), TOPDIR.joinpath('repo'),
|
'-o', MANDIR.joinpath('repo.1.tmp'), './repo',
|
||||||
'-h', '--help-all'])
|
'-h', '--help-all'])
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory() as tempdir:
|
||||||
repo_dir = Path(tempdir) / '.repo'
|
tempdir = Path(tempdir)
|
||||||
|
repo_dir = tempdir / '.repo'
|
||||||
repo_dir.mkdir()
|
repo_dir.mkdir()
|
||||||
(repo_dir / 'repo').symlink_to(TOPDIR)
|
(repo_dir / 'repo').symlink_to(TOPDIR)
|
||||||
|
|
||||||
|
# Create a repo wrapper using the active Python executable. We can't pass
|
||||||
|
# this directly to help2man as it's too simple, so insert it via shebang.
|
||||||
|
data = (TOPDIR / 'repo').read_text(encoding='utf-8')
|
||||||
|
tempbin = tempdir / 'repo'
|
||||||
|
tempbin.write_text(f'#!{sys.executable}\n' + data, encoding='utf-8')
|
||||||
|
tempbin.chmod(0o755)
|
||||||
|
|
||||||
# Run all cmd in parallel, and wait for them to finish.
|
# Run all cmd in parallel, and wait for them to finish.
|
||||||
with multiprocessing.Pool() as pool:
|
with multiprocessing.Pool() as pool:
|
||||||
pool.map(partial(worker, cwd=tempdir, check=True), cmdlist)
|
pool.map(partial(worker, cwd=tempdir, check=True), cmdlist)
|
||||||
|
22
repo
22
repo
@ -149,7 +149,7 @@ if not REPO_REV:
|
|||||||
BUG_URL = 'https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue'
|
BUG_URL = 'https://bugs.chromium.org/p/gerrit/issues/entry?template=Repo+tool+issue'
|
||||||
|
|
||||||
# increment this whenever we make important changes to this script
|
# increment this whenever we make important changes to this script
|
||||||
VERSION = (2, 21)
|
VERSION = (2, 29)
|
||||||
|
|
||||||
# increment this if the MAINTAINER_KEYS block is modified
|
# increment this if the MAINTAINER_KEYS block is modified
|
||||||
KEYRING_VERSION = (2, 3)
|
KEYRING_VERSION = (2, 3)
|
||||||
@ -316,6 +316,10 @@ def InitParser(parser, gitc_init=False):
|
|||||||
help='download the manifest as a static file '
|
help='download the manifest as a static file '
|
||||||
'rather then create a git checkout of '
|
'rather then create a git checkout of '
|
||||||
'the manifest repo')
|
'the manifest repo')
|
||||||
|
group.add_option('--manifest-depth', type='int', default=0, metavar='DEPTH',
|
||||||
|
help='create a shallow clone of the manifest repo with '
|
||||||
|
'given depth (0 for full clone); see git clone '
|
||||||
|
'(default: %default)')
|
||||||
|
|
||||||
# Options that only affect manifest project, and not any of the projects
|
# Options that only affect manifest project, and not any of the projects
|
||||||
# specified in the manifest itself.
|
# specified in the manifest itself.
|
||||||
@ -325,9 +329,9 @@ def InitParser(parser, gitc_init=False):
|
|||||||
# want -c, so try to satisfy both as best we can.
|
# want -c, so try to satisfy both as best we can.
|
||||||
if not gitc_init:
|
if not gitc_init:
|
||||||
cbr_opts += ['-c']
|
cbr_opts += ['-c']
|
||||||
group.add_option(*cbr_opts,
|
group.add_option(*cbr_opts, default=True,
|
||||||
dest='current_branch_only', action='store_true',
|
dest='current_branch_only', action='store_true',
|
||||||
help='fetch only current manifest branch from server')
|
help='fetch only current manifest branch from server (default)')
|
||||||
group.add_option('--no-current-branch',
|
group.add_option('--no-current-branch',
|
||||||
dest='current_branch_only', action='store_false',
|
dest='current_branch_only', action='store_false',
|
||||||
help='fetch all manifest branches from server')
|
help='fetch all manifest branches from server')
|
||||||
@ -612,15 +616,20 @@ def _Init(args, gitc_init=False):
|
|||||||
try:
|
try:
|
||||||
if not opt.quiet:
|
if not opt.quiet:
|
||||||
print('Downloading Repo source from', url)
|
print('Downloading Repo source from', url)
|
||||||
dst = os.path.abspath(os.path.join(repodir, S_repo))
|
dst_final = os.path.abspath(os.path.join(repodir, S_repo))
|
||||||
|
dst = dst_final + '.tmp'
|
||||||
|
shutil.rmtree(dst, ignore_errors=True)
|
||||||
_Clone(url, dst, opt.clone_bundle, opt.quiet, opt.verbose)
|
_Clone(url, dst, opt.clone_bundle, opt.quiet, opt.verbose)
|
||||||
|
|
||||||
remote_ref, rev = check_repo_rev(dst, rev, opt.repo_verify, quiet=opt.quiet)
|
remote_ref, rev = check_repo_rev(dst, rev, opt.repo_verify, quiet=opt.quiet)
|
||||||
_Checkout(dst, remote_ref, rev, opt.quiet)
|
_Checkout(dst, remote_ref, rev, opt.quiet)
|
||||||
|
|
||||||
if not os.path.isfile(os.path.join(dst, 'repo')):
|
if not os.path.isfile(os.path.join(dst, 'repo')):
|
||||||
print("warning: '%s' does not look like a git-repo repository, is "
|
print("fatal: '%s' does not look like a git-repo repository, is "
|
||||||
"REPO_URL set correctly?" % url, file=sys.stderr)
|
"--repo-url set correctly?" % url, file=sys.stderr)
|
||||||
|
raise CloneFailure()
|
||||||
|
|
||||||
|
os.rename(dst, dst_final)
|
||||||
|
|
||||||
except CloneFailure:
|
except CloneFailure:
|
||||||
print('fatal: double check your --repo-rev setting.', file=sys.stderr)
|
print('fatal: double check your --repo-rev setting.', file=sys.stderr)
|
||||||
@ -1317,6 +1326,7 @@ def main(orig_args):
|
|||||||
print("fatal: cloning the git-repo repository failed, will remove "
|
print("fatal: cloning the git-repo repository failed, will remove "
|
||||||
"'%s' " % path, file=sys.stderr)
|
"'%s' " % path, file=sys.stderr)
|
||||||
shutil.rmtree(path, ignore_errors=True)
|
shutil.rmtree(path, ignore_errors=True)
|
||||||
|
shutil.rmtree(path + '.tmp', ignore_errors=True)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
repo_main, rel_repo_dir = _FindRepo()
|
repo_main, rel_repo_dir = _FindRepo()
|
||||||
else:
|
else:
|
||||||
|
@ -60,8 +60,10 @@ change id will be added.
|
|||||||
capture_stderr=True)
|
capture_stderr=True)
|
||||||
status = p.Wait()
|
status = p.Wait()
|
||||||
|
|
||||||
print(p.stdout, file=sys.stdout)
|
if p.stdout:
|
||||||
print(p.stderr, file=sys.stderr)
|
print(p.stdout.strip(), file=sys.stdout)
|
||||||
|
if p.stderr:
|
||||||
|
print(p.stderr.strip(), file=sys.stderr)
|
||||||
|
|
||||||
if status == 0:
|
if status == 0:
|
||||||
# The cherry-pick was applied correctly. We just need to edit the
|
# The cherry-pick was applied correctly. We just need to edit the
|
||||||
|
@ -35,18 +35,21 @@ to the Unix 'patch' command.
|
|||||||
dest='absolute', action='store_true',
|
dest='absolute', action='store_true',
|
||||||
help='paths are relative to the repository root')
|
help='paths are relative to the repository root')
|
||||||
|
|
||||||
def _ExecuteOne(self, absolute, project):
|
def _ExecuteOne(self, absolute, local, project):
|
||||||
"""Obtains the diff for a specific project.
|
"""Obtains the diff for a specific project.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
absolute: Paths are relative to the root.
|
absolute: Paths are relative to the root.
|
||||||
|
local: a boolean, if True, the path is relative to the local
|
||||||
|
(sub)manifest. If false, the path is relative to the
|
||||||
|
outermost manifest.
|
||||||
project: Project to get status of.
|
project: Project to get status of.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The status of the project.
|
The status of the project.
|
||||||
"""
|
"""
|
||||||
buf = io.StringIO()
|
buf = io.StringIO()
|
||||||
ret = project.PrintWorkTreeDiff(absolute, output_redir=buf)
|
ret = project.PrintWorkTreeDiff(absolute, output_redir=buf, local=local)
|
||||||
return (ret, buf.getvalue())
|
return (ret, buf.getvalue())
|
||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
@ -63,7 +66,7 @@ to the Unix 'patch' command.
|
|||||||
|
|
||||||
return self.ExecuteInParallel(
|
return self.ExecuteInParallel(
|
||||||
opt.jobs,
|
opt.jobs,
|
||||||
functools.partial(self._ExecuteOne, opt.absolute),
|
functools.partial(self._ExecuteOne, opt.absolute, opt.this_manifest_only),
|
||||||
all_projects,
|
all_projects,
|
||||||
callback=_ProcessResults,
|
callback=_ProcessResults,
|
||||||
ordered=True)
|
ordered=True)
|
||||||
|
@ -118,6 +118,16 @@ synced and their revisions won't be found.
|
|||||||
self.printRevision(project.revisionExpr)
|
self.printRevision(project.revisionExpr)
|
||||||
self.out.nl()
|
self.out.nl()
|
||||||
|
|
||||||
|
if diff['missing']:
|
||||||
|
self.out.nl()
|
||||||
|
self.printText('missing projects : \n')
|
||||||
|
self.out.nl()
|
||||||
|
for project in diff['missing']:
|
||||||
|
self.printProject('\t%s' % (project.relpath))
|
||||||
|
self.printText(' at revision ')
|
||||||
|
self.printRevision(project.revisionExpr)
|
||||||
|
self.out.nl()
|
||||||
|
|
||||||
if diff['changed']:
|
if diff['changed']:
|
||||||
self.out.nl()
|
self.out.nl()
|
||||||
self.printText('changed projects : \n')
|
self.printText('changed projects : \n')
|
||||||
|
@ -84,6 +84,11 @@ REPO_PROJECT is set to the unique name of the project.
|
|||||||
|
|
||||||
REPO_PATH is the path relative the the root of the client.
|
REPO_PATH is the path relative the the root of the client.
|
||||||
|
|
||||||
|
REPO_OUTERPATH is the path of the sub manifest's root relative to the root of
|
||||||
|
the client.
|
||||||
|
|
||||||
|
REPO_INNERPATH is the path relative to the root of the sub manifest.
|
||||||
|
|
||||||
REPO_REMOTE is the name of the remote system from the manifest.
|
REPO_REMOTE is the name of the remote system from the manifest.
|
||||||
|
|
||||||
REPO_LREV is the name of the revision from the manifest, translated
|
REPO_LREV is the name of the revision from the manifest, translated
|
||||||
@ -290,8 +295,9 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
|
|||||||
env[name] = val
|
env[name] = val
|
||||||
|
|
||||||
setenv('REPO_PROJECT', project.name)
|
setenv('REPO_PROJECT', project.name)
|
||||||
setenv('REPO_PATH', project.relpath)
|
setenv('REPO_OUTERPATH', project.manifest.path_prefix)
|
||||||
setenv('REPO_OUTERPATH', project.RelPath(local=opt.this_manifest_only))
|
setenv('REPO_INNERPATH', project.relpath)
|
||||||
|
setenv('REPO_PATH', project.RelPath(local=opt.this_manifest_only))
|
||||||
setenv('REPO_REMOTE', project.remote.name)
|
setenv('REPO_REMOTE', project.remote.name)
|
||||||
try:
|
try:
|
||||||
# If we aren't in a fully synced state and we don't have the ref the manifest
|
# If we aren't in a fully synced state and we don't have the ref the manifest
|
||||||
|
@ -65,8 +65,7 @@ class Info(PagedCommand):
|
|||||||
self.manifest = self.manifest.outer_client
|
self.manifest = self.manifest.outer_client
|
||||||
manifestConfig = self.manifest.manifestProject.config
|
manifestConfig = self.manifest.manifestProject.config
|
||||||
mergeBranch = manifestConfig.GetBranch("default").merge
|
mergeBranch = manifestConfig.GetBranch("default").merge
|
||||||
manifestGroups = (manifestConfig.GetString('manifest.groups')
|
manifestGroups = self.manifest.GetGroupsStr()
|
||||||
or 'all,-notdefault')
|
|
||||||
|
|
||||||
self.heading("Manifest branch: ")
|
self.heading("Manifest branch: ")
|
||||||
if self.manifest.default.revisionExpr:
|
if self.manifest.default.revisionExpr:
|
||||||
|
@ -24,8 +24,6 @@ from error import ManifestParseError
|
|||||||
from project import SyncBuffer
|
from project import SyncBuffer
|
||||||
from git_config import GitConfig
|
from git_config import GitConfig
|
||||||
from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD
|
from git_command import git_require, MIN_GIT_VERSION_SOFT, MIN_GIT_VERSION_HARD
|
||||||
import fetch
|
|
||||||
import platform_utils
|
|
||||||
from wrapper import Wrapper
|
from wrapper import Wrapper
|
||||||
|
|
||||||
|
|
||||||
@ -91,11 +89,10 @@ to update the working directory files.
|
|||||||
def _Options(self, p, gitc_init=False):
|
def _Options(self, p, gitc_init=False):
|
||||||
Wrapper().InitParser(p, gitc_init=gitc_init)
|
Wrapper().InitParser(p, gitc_init=gitc_init)
|
||||||
m = p.add_option_group('Multi-manifest')
|
m = p.add_option_group('Multi-manifest')
|
||||||
m.add_option('--outer-manifest', action='store_true',
|
m.add_option('--outer-manifest', action='store_true', default=True,
|
||||||
help='operate starting at the outermost manifest')
|
help='operate starting at the outermost manifest')
|
||||||
m.add_option('--no-outer-manifest', dest='outer_manifest',
|
m.add_option('--no-outer-manifest', dest='outer_manifest',
|
||||||
action='store_false', default=None,
|
action='store_false', help='do not operate on outer manifests')
|
||||||
help='do not operate on outer manifests')
|
|
||||||
m.add_option('--this-manifest-only', action='store_true', default=None,
|
m.add_option('--this-manifest-only', action='store_true', default=None,
|
||||||
help='only operate on this (sub)manifest')
|
help='only operate on this (sub)manifest')
|
||||||
m.add_option('--no-this-manifest-only', '--all-manifests',
|
m.add_option('--no-this-manifest-only', '--all-manifests',
|
||||||
@ -112,6 +109,10 @@ to update the working directory files.
|
|||||||
Args:
|
Args:
|
||||||
opt: options from optparse.
|
opt: options from optparse.
|
||||||
"""
|
"""
|
||||||
|
# Normally this value is set when instantiating the project, but the
|
||||||
|
# manifest project is special and is created when instantiating the
|
||||||
|
# manifest which happens before we parse options.
|
||||||
|
self.manifest.manifestProject.clone_depth = opt.manifest_depth
|
||||||
if not self.manifest.manifestProject.Sync(
|
if not self.manifest.manifestProject.Sync(
|
||||||
manifest_url=opt.manifest_url,
|
manifest_url=opt.manifest_url,
|
||||||
manifest_branch=opt.manifest_branch,
|
manifest_branch=opt.manifest_branch,
|
||||||
@ -147,7 +148,7 @@ to update the working directory files.
|
|||||||
return value
|
return value
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def _ShouldConfigureUser(self, opt):
|
def _ShouldConfigureUser(self, opt, existing_checkout):
|
||||||
gc = self.client.globalConfig
|
gc = self.client.globalConfig
|
||||||
mp = self.manifest.manifestProject
|
mp = self.manifest.manifestProject
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ to update the working directory files.
|
|||||||
mp.config.SetString('user.name', gc.GetString('user.name'))
|
mp.config.SetString('user.name', gc.GetString('user.name'))
|
||||||
mp.config.SetString('user.email', gc.GetString('user.email'))
|
mp.config.SetString('user.email', gc.GetString('user.email'))
|
||||||
|
|
||||||
if not opt.quiet:
|
if not opt.quiet and not existing_checkout or opt.verbose:
|
||||||
print()
|
print()
|
||||||
print('Your identity is: %s <%s>' % (mp.config.GetString('user.name'),
|
print('Your identity is: %s <%s>' % (mp.config.GetString('user.name'),
|
||||||
mp.config.GetString('user.email')))
|
mp.config.GetString('user.email')))
|
||||||
@ -244,7 +245,7 @@ to update the working directory files.
|
|||||||
if current_dir != self.manifest.topdir:
|
if current_dir != self.manifest.topdir:
|
||||||
print('If this is not the directory in which you want to initialize '
|
print('If this is not the directory in which you want to initialize '
|
||||||
'repo, please run:')
|
'repo, please run:')
|
||||||
print(' rm -r %s/.repo' % self.manifest.topdir)
|
print(' rm -r %s' % os.path.join(self.manifest.topdir, '.repo'))
|
||||||
print('and try again.')
|
print('and try again.')
|
||||||
|
|
||||||
def ValidateOptions(self, opt, args):
|
def ValidateOptions(self, opt, args):
|
||||||
@ -260,6 +261,9 @@ to update the working directory files.
|
|||||||
if opt.use_superproject is not None:
|
if opt.use_superproject is not None:
|
||||||
self.OptionParser.error('--mirror and --use-superproject cannot be '
|
self.OptionParser.error('--mirror and --use-superproject cannot be '
|
||||||
'used together.')
|
'used together.')
|
||||||
|
if opt.archive and opt.use_superproject is not None:
|
||||||
|
self.OptionParser.error('--archive and --use-superproject cannot be used '
|
||||||
|
'together.')
|
||||||
|
|
||||||
if opt.standalone_manifest and (opt.manifest_branch or
|
if opt.standalone_manifest and (opt.manifest_branch or
|
||||||
opt.manifest_name != 'default.xml'):
|
opt.manifest_name != 'default.xml'):
|
||||||
@ -311,10 +315,17 @@ to update the working directory files.
|
|||||||
# Older versions of git supported worktree, but had dangerous gc bugs.
|
# Older versions of git supported worktree, but had dangerous gc bugs.
|
||||||
git_require((2, 15, 0), fail=True, msg='git gc worktree corruption')
|
git_require((2, 15, 0), fail=True, msg='git gc worktree corruption')
|
||||||
|
|
||||||
|
# Provide a short notice that we're reinitializing an existing checkout.
|
||||||
|
# Sometimes developers might not realize that they're in one, or that
|
||||||
|
# repo doesn't do nested checkouts.
|
||||||
|
existing_checkout = self.manifest.manifestProject.Exists
|
||||||
|
if not opt.quiet and existing_checkout:
|
||||||
|
print('repo: reusing existing repo client checkout in', self.manifest.topdir)
|
||||||
|
|
||||||
self._SyncManifest(opt)
|
self._SyncManifest(opt)
|
||||||
|
|
||||||
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
|
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
|
||||||
if opt.config_name or self._ShouldConfigureUser(opt):
|
if opt.config_name or self._ShouldConfigureUser(opt, existing_checkout):
|
||||||
self._ConfigureUser(opt)
|
self._ConfigureUser(opt)
|
||||||
self._ConfigureColor()
|
self._ConfigureColor()
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ need to be performed by an end-user.
|
|||||||
_PostRepoUpgrade(self.manifest)
|
_PostRepoUpgrade(self.manifest)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not rp.Sync_NetworkHalf():
|
if not rp.Sync_NetworkHalf().success:
|
||||||
print("error: can't update repo", file=sys.stderr)
|
print("error: can't update repo", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ The '%prog' command stages files to prepare the next commit.
|
|||||||
out.nl()
|
out.nl()
|
||||||
|
|
||||||
out.prompt('project> ')
|
out.prompt('project> ')
|
||||||
|
out.flush()
|
||||||
try:
|
try:
|
||||||
a = sys.stdin.readline()
|
a = sys.stdin.readline()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
@ -83,7 +83,7 @@ the following meanings:
|
|||||||
dest='orphans', action='store_true',
|
dest='orphans', action='store_true',
|
||||||
help="include objects in working directory outside of repo projects")
|
help="include objects in working directory outside of repo projects")
|
||||||
|
|
||||||
def _StatusHelper(self, quiet, project):
|
def _StatusHelper(self, quiet, local, project):
|
||||||
"""Obtains the status for a specific project.
|
"""Obtains the status for a specific project.
|
||||||
|
|
||||||
Obtains the status for a project, redirecting the output to
|
Obtains the status for a project, redirecting the output to
|
||||||
@ -91,13 +91,17 @@ the following meanings:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
quiet: Where to output the status.
|
quiet: Where to output the status.
|
||||||
|
local: a boolean, if True, the path is relative to the local
|
||||||
|
(sub)manifest. If false, the path is relative to the
|
||||||
|
outermost manifest.
|
||||||
project: Project to get status of.
|
project: Project to get status of.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The status of the project.
|
The status of the project.
|
||||||
"""
|
"""
|
||||||
buf = io.StringIO()
|
buf = io.StringIO()
|
||||||
ret = project.PrintWorkTreeStatus(quiet=quiet, output_redir=buf)
|
ret = project.PrintWorkTreeStatus(quiet=quiet, output_redir=buf,
|
||||||
|
local=local)
|
||||||
return (ret, buf.getvalue())
|
return (ret, buf.getvalue())
|
||||||
|
|
||||||
def _FindOrphans(self, dirs, proj_dirs, proj_dirs_parents, outstring):
|
def _FindOrphans(self, dirs, proj_dirs, proj_dirs_parents, outstring):
|
||||||
@ -130,7 +134,7 @@ the following meanings:
|
|||||||
|
|
||||||
counter = self.ExecuteInParallel(
|
counter = self.ExecuteInParallel(
|
||||||
opt.jobs,
|
opt.jobs,
|
||||||
functools.partial(self._StatusHelper, opt.quiet),
|
functools.partial(self._StatusHelper, opt.quiet, opt.this_manifest_only),
|
||||||
all_projects,
|
all_projects,
|
||||||
callback=_ProcessResults,
|
callback=_ProcessResults,
|
||||||
ordered=True)
|
ordered=True)
|
||||||
|
567
subcmds/sync.py
567
subcmds/sync.py
@ -12,6 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import collections
|
||||||
import functools
|
import functools
|
||||||
import http.cookiejar as cookielib
|
import http.cookiejar as cookielib
|
||||||
import io
|
import io
|
||||||
@ -20,13 +21,16 @@ import multiprocessing
|
|||||||
import netrc
|
import netrc
|
||||||
from optparse import SUPPRESS_HELP
|
from optparse import SUPPRESS_HELP
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
from typing import NamedTuple, List, Set
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
import xml.parsers.expat
|
||||||
import xmlrpc.client
|
import xmlrpc.client
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -51,22 +55,78 @@ import git_superproject
|
|||||||
import gitc_utils
|
import gitc_utils
|
||||||
from project import Project
|
from project import Project
|
||||||
from project import RemoteSpec
|
from project import RemoteSpec
|
||||||
from command import Command, MirrorSafeCommand, WORKER_BATCH_SIZE
|
from command import Command, DEFAULT_LOCAL_JOBS, MirrorSafeCommand, WORKER_BATCH_SIZE
|
||||||
from error import RepoChangedException, GitError, ManifestParseError
|
from error import RepoChangedException, GitError, ManifestParseError
|
||||||
import platform_utils
|
import platform_utils
|
||||||
from project import SyncBuffer
|
from project import SyncBuffer
|
||||||
from progress import Progress
|
from progress import Progress
|
||||||
|
from repo_trace import IsTrace, Trace
|
||||||
import ssh
|
import ssh
|
||||||
from wrapper import Wrapper
|
from wrapper import Wrapper
|
||||||
from manifest_xml import GitcManifest
|
from manifest_xml import GitcManifest
|
||||||
|
|
||||||
_ONE_DAY_S = 24 * 60 * 60
|
_ONE_DAY_S = 24 * 60 * 60
|
||||||
|
# Env var to implicitly turn off object backups.
|
||||||
|
REPO_BACKUP_OBJECTS = 'REPO_BACKUP_OBJECTS'
|
||||||
|
|
||||||
|
_BACKUP_OBJECTS = os.environ.get(REPO_BACKUP_OBJECTS) != '0'
|
||||||
|
|
||||||
|
|
||||||
|
class _FetchOneResult(NamedTuple):
|
||||||
|
"""_FetchOne return value.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
success (bool): True if successful.
|
||||||
|
project (Project): The fetched project.
|
||||||
|
start (float): The starting time.time().
|
||||||
|
finish (float): The ending time.time().
|
||||||
|
remote_fetched (bool): True if the remote was actually queried.
|
||||||
|
"""
|
||||||
|
success: bool
|
||||||
|
project: Project
|
||||||
|
start: float
|
||||||
|
finish: float
|
||||||
|
remote_fetched: bool
|
||||||
|
|
||||||
|
|
||||||
|
class _FetchResult(NamedTuple):
|
||||||
|
"""_Fetch return value.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
success (bool): True if successful.
|
||||||
|
projects (Set[str]): The names of the git directories of fetched projects.
|
||||||
|
"""
|
||||||
|
success: bool
|
||||||
|
projects: Set[str]
|
||||||
|
|
||||||
|
|
||||||
|
class _FetchMainResult(NamedTuple):
|
||||||
|
"""_FetchMain return value.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
all_projects (List[Project]): The fetched projects.
|
||||||
|
"""
|
||||||
|
all_projects: List[Project]
|
||||||
|
|
||||||
|
|
||||||
|
class _CheckoutOneResult(NamedTuple):
|
||||||
|
"""_CheckoutOne return value.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
success (bool): True if successful.
|
||||||
|
project (Project): The project.
|
||||||
|
start (float): The starting time.time().
|
||||||
|
finish (float): The ending time.time().
|
||||||
|
"""
|
||||||
|
success: bool
|
||||||
|
project: Project
|
||||||
|
start: float
|
||||||
|
finish: float
|
||||||
|
|
||||||
|
|
||||||
class Sync(Command, MirrorSafeCommand):
|
class Sync(Command, MirrorSafeCommand):
|
||||||
jobs = 1
|
|
||||||
COMMON = True
|
COMMON = True
|
||||||
MULTI_MANIFEST_SUPPORT = False
|
MULTI_MANIFEST_SUPPORT = True
|
||||||
helpSummary = "Update working tree to the latest revision"
|
helpSummary = "Update working tree to the latest revision"
|
||||||
helpUsage = """
|
helpUsage = """
|
||||||
%prog [<project>...]
|
%prog [<project>...]
|
||||||
@ -167,21 +227,16 @@ If the remote SSH daemon is Gerrit Code Review, version 2.0.10 or
|
|||||||
later is required to fix a server side protocol bug.
|
later is required to fix a server side protocol bug.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
PARALLEL_JOBS = 1
|
# A value of 0 means we want parallel jobs, but we'll determine the default
|
||||||
|
# value later on.
|
||||||
def _CommonOptions(self, p):
|
PARALLEL_JOBS = 0
|
||||||
if self.manifest:
|
|
||||||
try:
|
|
||||||
self.PARALLEL_JOBS = self.manifest.default.sync_j
|
|
||||||
except ManifestParseError:
|
|
||||||
pass
|
|
||||||
super()._CommonOptions(p)
|
|
||||||
|
|
||||||
def _Options(self, p, show_smart=True):
|
def _Options(self, p, show_smart=True):
|
||||||
p.add_option('--jobs-network', default=None, type=int, metavar='JOBS',
|
p.add_option('--jobs-network', default=None, type=int, metavar='JOBS',
|
||||||
help='number of network jobs to run in parallel (defaults to --jobs)')
|
help='number of network jobs to run in parallel (defaults to --jobs or 1)')
|
||||||
p.add_option('--jobs-checkout', default=None, type=int, metavar='JOBS',
|
p.add_option('--jobs-checkout', default=None, type=int, metavar='JOBS',
|
||||||
help='number of local checkout jobs to run in parallel (defaults to --jobs)')
|
help='number of local checkout jobs to run in parallel (defaults to --jobs or '
|
||||||
|
f'{DEFAULT_LOCAL_JOBS})')
|
||||||
|
|
||||||
p.add_option('-f', '--force-broken',
|
p.add_option('-f', '--force-broken',
|
||||||
dest='force_broken', action='store_true',
|
dest='force_broken', action='store_true',
|
||||||
@ -270,68 +325,117 @@ later is required to fix a server side protocol bug.
|
|||||||
dest='repo_upgraded', action='store_true',
|
dest='repo_upgraded', action='store_true',
|
||||||
help=SUPPRESS_HELP)
|
help=SUPPRESS_HELP)
|
||||||
|
|
||||||
def _GetBranch(self):
|
def _GetBranch(self, manifest_project):
|
||||||
"""Returns the branch name for getting the approved manifest."""
|
"""Returns the branch name for getting the approved smartsync manifest.
|
||||||
p = self.manifest.manifestProject
|
|
||||||
b = p.GetBranch(p.CurrentBranch)
|
Args:
|
||||||
|
manifest_project: the manifestProject to query.
|
||||||
|
"""
|
||||||
|
b = manifest_project.GetBranch(manifest_project.CurrentBranch)
|
||||||
branch = b.merge
|
branch = b.merge
|
||||||
if branch.startswith(R_HEADS):
|
if branch.startswith(R_HEADS):
|
||||||
branch = branch[len(R_HEADS):]
|
branch = branch[len(R_HEADS):]
|
||||||
return branch
|
return branch
|
||||||
|
|
||||||
def _GetCurrentBranchOnly(self, opt):
|
def _GetCurrentBranchOnly(self, opt, manifest):
|
||||||
"""Returns whether current-branch or use-superproject options are enabled.
|
"""Returns whether current-branch or use-superproject options are enabled.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt: Program options returned from optparse. See _Options().
|
||||||
|
manifest: The manifest to use.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if a superproject is requested, otherwise the value of the
|
True if a superproject is requested, otherwise the value of the
|
||||||
current_branch option (True, False or None).
|
current_branch option (True, False or None).
|
||||||
"""
|
"""
|
||||||
return git_superproject.UseSuperproject(opt, self.manifest) or opt.current_branch_only
|
return git_superproject.UseSuperproject(opt.use_superproject, manifest) or opt.current_branch_only
|
||||||
|
|
||||||
def _UpdateProjectsRevisionId(self, opt, args, load_local_manifests, superproject_logging_data):
|
def _UpdateProjectsRevisionId(self, opt, args, superproject_logging_data,
|
||||||
"""Update revisionId of every project with the SHA from superproject.
|
manifest):
|
||||||
|
"""Update revisionId of projects with the commit hash from the superproject.
|
||||||
|
|
||||||
This function updates each project's revisionId with SHA from superproject.
|
This function updates each project's revisionId with the commit hash from
|
||||||
It writes the updated manifest into a file and reloads the manifest from it.
|
the superproject. It writes the updated manifest into a file and reloads
|
||||||
|
the manifest from it. When appropriate, sub manifests are also processed.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
opt: Program options returned from optparse. See _Options().
|
opt: Program options returned from optparse. See _Options().
|
||||||
args: Arguments to pass to GetProjects. See the GetProjects
|
args: Arguments to pass to GetProjects. See the GetProjects
|
||||||
docstring for details.
|
docstring for details.
|
||||||
load_local_manifests: Whether to load local manifests.
|
superproject_logging_data: A dictionary of superproject data to log.
|
||||||
superproject_logging_data: A dictionary of superproject data that is to be logged.
|
manifest: The manifest to use.
|
||||||
|
|
||||||
Returns:
|
|
||||||
Returns path to the overriding manifest file instead of None.
|
|
||||||
"""
|
"""
|
||||||
superproject = self.manifest.superproject
|
have_superproject = manifest.superproject or any(
|
||||||
superproject.SetQuiet(opt.quiet)
|
m.superproject for m in manifest.all_children)
|
||||||
print_messages = git_superproject.PrintMessages(opt, self.manifest)
|
if not have_superproject:
|
||||||
superproject.SetPrintMessages(print_messages)
|
return
|
||||||
if opt.local_only:
|
|
||||||
manifest_path = superproject.manifest_path
|
if opt.local_only and manifest.superproject:
|
||||||
|
manifest_path = manifest.superproject.manifest_path
|
||||||
if manifest_path:
|
if manifest_path:
|
||||||
self._ReloadManifest(manifest_path, load_local_manifests)
|
self._ReloadManifest(manifest_path, manifest)
|
||||||
return manifest_path
|
return
|
||||||
|
|
||||||
all_projects = self.GetProjects(args,
|
all_projects = self.GetProjects(args,
|
||||||
missing_ok=True,
|
missing_ok=True,
|
||||||
submodules_ok=opt.fetch_submodules)
|
submodules_ok=opt.fetch_submodules,
|
||||||
update_result = superproject.UpdateProjectsRevisionId(
|
manifest=manifest,
|
||||||
all_projects, git_event_log=self.git_event_log)
|
all_manifests=not opt.this_manifest_only)
|
||||||
|
|
||||||
|
per_manifest = collections.defaultdict(list)
|
||||||
|
manifest_paths = {}
|
||||||
|
if opt.this_manifest_only:
|
||||||
|
per_manifest[manifest.path_prefix] = all_projects
|
||||||
|
else:
|
||||||
|
for p in all_projects:
|
||||||
|
per_manifest[p.manifest.path_prefix].append(p)
|
||||||
|
|
||||||
|
superproject_logging_data = {}
|
||||||
|
need_unload = False
|
||||||
|
for m in self.ManifestList(opt):
|
||||||
|
if not m.path_prefix in per_manifest:
|
||||||
|
continue
|
||||||
|
use_super = git_superproject.UseSuperproject(opt.use_superproject, m)
|
||||||
|
if superproject_logging_data:
|
||||||
|
superproject_logging_data['multimanifest'] = True
|
||||||
|
superproject_logging_data.update(
|
||||||
|
superproject=use_super,
|
||||||
|
haslocalmanifests=bool(m.HasLocalManifests),
|
||||||
|
hassuperprojecttag=bool(m.superproject),
|
||||||
|
)
|
||||||
|
if use_super and (m.IsMirror or m.IsArchive):
|
||||||
|
# Don't use superproject, because we have no working tree.
|
||||||
|
use_super = False
|
||||||
|
superproject_logging_data['superproject'] = False
|
||||||
|
superproject_logging_data['noworktree'] = True
|
||||||
|
if opt.use_superproject is not False:
|
||||||
|
print(f'{m.path_prefix}: not using superproject because there is no '
|
||||||
|
'working tree.')
|
||||||
|
|
||||||
|
if not use_super:
|
||||||
|
continue
|
||||||
|
m.superproject.SetQuiet(opt.quiet)
|
||||||
|
print_messages = git_superproject.PrintMessages(opt.use_superproject, m)
|
||||||
|
m.superproject.SetPrintMessages(print_messages)
|
||||||
|
update_result = m.superproject.UpdateProjectsRevisionId(
|
||||||
|
per_manifest[m.path_prefix], git_event_log=self.git_event_log)
|
||||||
manifest_path = update_result.manifest_path
|
manifest_path = update_result.manifest_path
|
||||||
superproject_logging_data['updatedrevisionid'] = bool(manifest_path)
|
superproject_logging_data['updatedrevisionid'] = bool(manifest_path)
|
||||||
if manifest_path:
|
if manifest_path:
|
||||||
self._ReloadManifest(manifest_path, load_local_manifests)
|
m.SetManifestOverride(manifest_path)
|
||||||
|
need_unload = True
|
||||||
else:
|
else:
|
||||||
if print_messages:
|
if print_messages:
|
||||||
print('warning: Update of revisionId from superproject has failed, '
|
print(f'{m.path_prefix}: warning: Update of revisionId from '
|
||||||
'repo sync will not use superproject to fetch the source. ',
|
'superproject has failed, repo sync will not use superproject '
|
||||||
'Please resync with the --no-use-superproject option to avoid this repo warning.',
|
'to fetch the source. ',
|
||||||
|
'Please resync with the --no-use-superproject option to avoid '
|
||||||
|
'this repo warning.',
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
if update_result.fatal and opt.use_superproject is not None:
|
if update_result.fatal and opt.use_superproject is not None:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return manifest_path
|
if need_unload:
|
||||||
|
m.outer_client.manifest.Unload()
|
||||||
|
|
||||||
def _FetchProjectList(self, opt, projects):
|
def _FetchProjectList(self, opt, projects):
|
||||||
"""Main function of the fetch worker.
|
"""Main function of the fetch worker.
|
||||||
@ -361,20 +465,21 @@ later is required to fix a server side protocol bug.
|
|||||||
success = False
|
success = False
|
||||||
buf = io.StringIO()
|
buf = io.StringIO()
|
||||||
try:
|
try:
|
||||||
success = project.Sync_NetworkHalf(
|
sync_result = project.Sync_NetworkHalf(
|
||||||
quiet=opt.quiet,
|
quiet=opt.quiet,
|
||||||
verbose=opt.verbose,
|
verbose=opt.verbose,
|
||||||
output_redir=buf,
|
output_redir=buf,
|
||||||
current_branch_only=self._GetCurrentBranchOnly(opt),
|
current_branch_only=self._GetCurrentBranchOnly(opt, project.manifest),
|
||||||
force_sync=opt.force_sync,
|
force_sync=opt.force_sync,
|
||||||
clone_bundle=opt.clone_bundle,
|
clone_bundle=opt.clone_bundle,
|
||||||
tags=opt.tags, archive=self.manifest.IsArchive,
|
tags=opt.tags, archive=project.manifest.IsArchive,
|
||||||
optimized_fetch=opt.optimized_fetch,
|
optimized_fetch=opt.optimized_fetch,
|
||||||
retry_fetches=opt.retry_fetches,
|
retry_fetches=opt.retry_fetches,
|
||||||
prune=opt.prune,
|
prune=opt.prune,
|
||||||
ssh_proxy=self.ssh_proxy,
|
ssh_proxy=self.ssh_proxy,
|
||||||
clone_filter=self.manifest.CloneFilter,
|
clone_filter=project.manifest.CloneFilter,
|
||||||
partial_clone_exclude=self.manifest.PartialCloneExclude)
|
partial_clone_exclude=project.manifest.PartialCloneExclude)
|
||||||
|
success = sync_result.success
|
||||||
|
|
||||||
output = buf.getvalue()
|
output = buf.getvalue()
|
||||||
if (opt.verbose or not success) and output:
|
if (opt.verbose or not success) and output:
|
||||||
@ -392,7 +497,8 @@ later is required to fix a server side protocol bug.
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
finish = time.time()
|
finish = time.time()
|
||||||
return (success, project, start, finish)
|
return _FetchOneResult(success, project, start, finish,
|
||||||
|
sync_result.remote_fetched)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _FetchInitChild(cls, ssh_proxy):
|
def _FetchInitChild(cls, ssh_proxy):
|
||||||
@ -401,8 +507,9 @@ later is required to fix a server side protocol bug.
|
|||||||
def _Fetch(self, projects, opt, err_event, ssh_proxy):
|
def _Fetch(self, projects, opt, err_event, ssh_proxy):
|
||||||
ret = True
|
ret = True
|
||||||
|
|
||||||
jobs = opt.jobs_network if opt.jobs_network else self.jobs
|
jobs = opt.jobs_network
|
||||||
fetched = set()
|
fetched = set()
|
||||||
|
remote_fetched = set()
|
||||||
pm = Progress('Fetching', len(projects), delay=False, quiet=opt.quiet)
|
pm = Progress('Fetching', len(projects), delay=False, quiet=opt.quiet)
|
||||||
|
|
||||||
objdir_project_map = dict()
|
objdir_project_map = dict()
|
||||||
@ -413,10 +520,16 @@ later is required to fix a server side protocol bug.
|
|||||||
def _ProcessResults(results_sets):
|
def _ProcessResults(results_sets):
|
||||||
ret = True
|
ret = True
|
||||||
for results in results_sets:
|
for results in results_sets:
|
||||||
for (success, project, start, finish) in results:
|
for result in results:
|
||||||
|
success = result.success
|
||||||
|
project = result.project
|
||||||
|
start = result.start
|
||||||
|
finish = result.finish
|
||||||
self._fetch_times.Set(project, finish - start)
|
self._fetch_times.Set(project, finish - start)
|
||||||
self.event_log.AddSync(project, event_log.TASK_SYNC_NETWORK,
|
self.event_log.AddSync(project, event_log.TASK_SYNC_NETWORK,
|
||||||
start, finish, success)
|
start, finish, success)
|
||||||
|
if result.remote_fetched:
|
||||||
|
remote_fetched.add(project)
|
||||||
# Check for any errors before running any more tasks.
|
# Check for any errors before running any more tasks.
|
||||||
# ...we'll let existing jobs finish, though.
|
# ...we'll let existing jobs finish, though.
|
||||||
if not success:
|
if not success:
|
||||||
@ -471,13 +584,13 @@ later is required to fix a server side protocol bug.
|
|||||||
pm.end()
|
pm.end()
|
||||||
self._fetch_times.Save()
|
self._fetch_times.Save()
|
||||||
|
|
||||||
if not self.manifest.IsArchive:
|
if not self.outer_client.manifest.IsArchive:
|
||||||
self._GCProjects(projects, opt, err_event)
|
self._GCProjects(projects, opt, err_event)
|
||||||
|
|
||||||
return (ret, fetched)
|
return _FetchResult(ret, fetched)
|
||||||
|
|
||||||
def _FetchMain(self, opt, args, all_projects, err_event, manifest_name,
|
def _FetchMain(self, opt, args, all_projects, err_event,
|
||||||
load_local_manifests, ssh_proxy):
|
ssh_proxy, manifest):
|
||||||
"""The main network fetch loop.
|
"""The main network fetch loop.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -485,14 +598,13 @@ later is required to fix a server side protocol bug.
|
|||||||
args: Command line args used to filter out projects.
|
args: Command line args used to filter out projects.
|
||||||
all_projects: List of all projects that should be fetched.
|
all_projects: List of all projects that should be fetched.
|
||||||
err_event: Whether an error was hit while processing.
|
err_event: Whether an error was hit while processing.
|
||||||
manifest_name: Manifest file to be reloaded.
|
|
||||||
load_local_manifests: Whether to load local manifests.
|
|
||||||
ssh_proxy: SSH manager for clients & masters.
|
ssh_proxy: SSH manager for clients & masters.
|
||||||
|
manifest: The manifest to use.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List of all projects that should be checked out.
|
List of all projects that should be checked out.
|
||||||
"""
|
"""
|
||||||
rp = self.manifest.repoProject
|
rp = manifest.repoProject
|
||||||
|
|
||||||
to_fetch = []
|
to_fetch = []
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@ -501,7 +613,9 @@ later is required to fix a server side protocol bug.
|
|||||||
to_fetch.extend(all_projects)
|
to_fetch.extend(all_projects)
|
||||||
to_fetch.sort(key=self._fetch_times.Get, reverse=True)
|
to_fetch.sort(key=self._fetch_times.Get, reverse=True)
|
||||||
|
|
||||||
success, fetched = self._Fetch(to_fetch, opt, err_event, ssh_proxy)
|
result = self._Fetch(to_fetch, opt, err_event, ssh_proxy)
|
||||||
|
success = result.success
|
||||||
|
fetched = result.projects
|
||||||
if not success:
|
if not success:
|
||||||
err_event.set()
|
err_event.set()
|
||||||
|
|
||||||
@ -511,15 +625,17 @@ later is required to fix a server side protocol bug.
|
|||||||
if err_event.is_set():
|
if err_event.is_set():
|
||||||
print('\nerror: Exited sync due to fetch errors.\n', file=sys.stderr)
|
print('\nerror: Exited sync due to fetch errors.\n', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return
|
return _FetchMainResult([])
|
||||||
|
|
||||||
# Iteratively fetch missing and/or nested unregistered submodules
|
# Iteratively fetch missing and/or nested unregistered submodules
|
||||||
previously_missing_set = set()
|
previously_missing_set = set()
|
||||||
while True:
|
while True:
|
||||||
self._ReloadManifest(manifest_name, load_local_manifests)
|
self._ReloadManifest(None, manifest)
|
||||||
all_projects = self.GetProjects(args,
|
all_projects = self.GetProjects(args,
|
||||||
missing_ok=True,
|
missing_ok=True,
|
||||||
submodules_ok=opt.fetch_submodules)
|
submodules_ok=opt.fetch_submodules,
|
||||||
|
manifest=manifest,
|
||||||
|
all_manifests=not opt.this_manifest_only)
|
||||||
missing = []
|
missing = []
|
||||||
for project in all_projects:
|
for project in all_projects:
|
||||||
if project.gitdir not in fetched:
|
if project.gitdir not in fetched:
|
||||||
@ -532,12 +648,14 @@ later is required to fix a server side protocol bug.
|
|||||||
if previously_missing_set == missing_set:
|
if previously_missing_set == missing_set:
|
||||||
break
|
break
|
||||||
previously_missing_set = missing_set
|
previously_missing_set = missing_set
|
||||||
success, new_fetched = self._Fetch(missing, opt, err_event, ssh_proxy)
|
result = self._Fetch(missing, opt, err_event, ssh_proxy)
|
||||||
|
success = result.success
|
||||||
|
new_fetched = result.projects
|
||||||
if not success:
|
if not success:
|
||||||
err_event.set()
|
err_event.set()
|
||||||
fetched.update(new_fetched)
|
fetched.update(new_fetched)
|
||||||
|
|
||||||
return all_projects
|
return _FetchMainResult(all_projects)
|
||||||
|
|
||||||
def _CheckoutOne(self, detach_head, force_sync, project):
|
def _CheckoutOne(self, detach_head, force_sync, project):
|
||||||
"""Checkout work tree for one project
|
"""Checkout work tree for one project
|
||||||
@ -551,7 +669,7 @@ later is required to fix a server side protocol bug.
|
|||||||
Whether the fetch was successful.
|
Whether the fetch was successful.
|
||||||
"""
|
"""
|
||||||
start = time.time()
|
start = time.time()
|
||||||
syncbuf = SyncBuffer(self.manifest.manifestProject.config,
|
syncbuf = SyncBuffer(project.manifest.manifestProject.config,
|
||||||
detach_head=detach_head)
|
detach_head=detach_head)
|
||||||
success = False
|
success = False
|
||||||
try:
|
try:
|
||||||
@ -569,7 +687,7 @@ later is required to fix a server side protocol bug.
|
|||||||
if not success:
|
if not success:
|
||||||
print('error: Cannot checkout %s' % (project.name), file=sys.stderr)
|
print('error: Cannot checkout %s' % (project.name), file=sys.stderr)
|
||||||
finish = time.time()
|
finish = time.time()
|
||||||
return (success, project, start, finish)
|
return _CheckoutOneResult(success, project, start, finish)
|
||||||
|
|
||||||
def _Checkout(self, all_projects, opt, err_results):
|
def _Checkout(self, all_projects, opt, err_results):
|
||||||
"""Checkout projects listed in all_projects
|
"""Checkout projects listed in all_projects
|
||||||
@ -584,7 +702,11 @@ later is required to fix a server side protocol bug.
|
|||||||
|
|
||||||
def _ProcessResults(pool, pm, results):
|
def _ProcessResults(pool, pm, results):
|
||||||
ret = True
|
ret = True
|
||||||
for (success, project, start, finish) in results:
|
for result in results:
|
||||||
|
success = result.success
|
||||||
|
project = result.project
|
||||||
|
start = result.start
|
||||||
|
finish = result.finish
|
||||||
self.event_log.AddSync(project, event_log.TASK_SYNC_LOCAL,
|
self.event_log.AddSync(project, event_log.TASK_SYNC_LOCAL,
|
||||||
start, finish, success)
|
start, finish, success)
|
||||||
# Check for any errors before running any more tasks.
|
# Check for any errors before running any more tasks.
|
||||||
@ -600,21 +722,57 @@ later is required to fix a server side protocol bug.
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
return self.ExecuteInParallel(
|
return self.ExecuteInParallel(
|
||||||
opt.jobs_checkout if opt.jobs_checkout else self.jobs,
|
opt.jobs_checkout,
|
||||||
functools.partial(self._CheckoutOne, opt.detach_head, opt.force_sync),
|
functools.partial(self._CheckoutOne, opt.detach_head, opt.force_sync),
|
||||||
all_projects,
|
all_projects,
|
||||||
callback=_ProcessResults,
|
callback=_ProcessResults,
|
||||||
output=Progress('Checking out', len(all_projects), quiet=opt.quiet)) and not err_results
|
output=Progress('Checking out', len(all_projects), quiet=opt.quiet)) and not err_results
|
||||||
|
|
||||||
|
def _backup_cruft(self, bare_git):
|
||||||
|
"""Save a copy of any cruft from `git gc`."""
|
||||||
|
# Find any cruft packs in the current gitdir, and save them.
|
||||||
|
# b/221065125 (repo sync complains that objects are missing). This does
|
||||||
|
# not prevent that state, but makes it so that the missing objects are
|
||||||
|
# available.
|
||||||
|
objdir = bare_git._project.objdir
|
||||||
|
pack_dir = os.path.join(objdir, 'pack')
|
||||||
|
bak_dir = os.path.join(objdir, '.repo', 'pack.bak')
|
||||||
|
if not _BACKUP_OBJECTS or not platform_utils.isdir(pack_dir):
|
||||||
|
return
|
||||||
|
saved = []
|
||||||
|
files = set(platform_utils.listdir(pack_dir))
|
||||||
|
to_backup = []
|
||||||
|
for f in files:
|
||||||
|
base, ext = os.path.splitext(f)
|
||||||
|
if base + '.mtimes' in files:
|
||||||
|
to_backup.append(f)
|
||||||
|
if to_backup:
|
||||||
|
os.makedirs(bak_dir, exist_ok=True)
|
||||||
|
for fname in to_backup:
|
||||||
|
bak_fname = os.path.join(bak_dir, fname)
|
||||||
|
if not os.path.exists(bak_fname):
|
||||||
|
saved.append(fname)
|
||||||
|
# Use a tmp file so that we are sure of a complete copy.
|
||||||
|
shutil.copy(os.path.join(pack_dir, fname), bak_fname + '.tmp')
|
||||||
|
shutil.move(bak_fname + '.tmp', bak_fname)
|
||||||
|
if saved:
|
||||||
|
Trace('%s saved %s', bare_git._project.name, ' '.join(saved))
|
||||||
|
|
||||||
def _GCProjects(self, projects, opt, err_event):
|
def _GCProjects(self, projects, opt, err_event):
|
||||||
pm = Progress('Garbage collecting', len(projects), delay=False, quiet=opt.quiet)
|
pm = Progress('Garbage collecting', len(projects), delay=False, quiet=opt.quiet)
|
||||||
pm.update(inc=0, msg='prescan')
|
pm.update(inc=0, msg='prescan')
|
||||||
|
|
||||||
tidy_dirs = {}
|
tidy_dirs = {}
|
||||||
for project in projects:
|
for project in projects:
|
||||||
# Make sure pruning never kicks in with shared projects.
|
# Make sure pruning never kicks in with shared projects that do not use
|
||||||
|
# alternates to avoid corruption.
|
||||||
if (not project.use_git_worktrees and
|
if (not project.use_git_worktrees and
|
||||||
len(project.manifest.GetProjectsWithName(project.name)) > 1):
|
len(project.manifest.GetProjectsWithName(project.name, all_manifests=True)) > 1):
|
||||||
|
if project.UseAlternates:
|
||||||
|
# Undo logic set by previous versions of repo.
|
||||||
|
project.config.SetString('extensions.preciousObjects', None)
|
||||||
|
project.config.SetString('gc.pruneExpire', None)
|
||||||
|
else:
|
||||||
if not opt.quiet:
|
if not opt.quiet:
|
||||||
print('\r%s: Shared project %s found, disabling pruning.' %
|
print('\r%s: Shared project %s found, disabling pruning.' %
|
||||||
(project.relpath, project.name))
|
(project.relpath, project.name))
|
||||||
@ -640,19 +798,28 @@ later is required to fix a server side protocol bug.
|
|||||||
project.bare_git,
|
project.bare_git,
|
||||||
)
|
)
|
||||||
|
|
||||||
cpu_count = os.cpu_count()
|
jobs = opt.jobs
|
||||||
jobs = min(self.jobs, cpu_count)
|
|
||||||
|
|
||||||
|
gc_args = ['--auto']
|
||||||
|
backup_cruft = False
|
||||||
|
if git_require((2, 37, 0)):
|
||||||
|
gc_args.append('--cruft')
|
||||||
|
backup_cruft = True
|
||||||
|
pack_refs_args = ()
|
||||||
if jobs < 2:
|
if jobs < 2:
|
||||||
for (run_gc, bare_git) in tidy_dirs.values():
|
for (run_gc, bare_git) in tidy_dirs.values():
|
||||||
pm.update(msg=bare_git._project.name)
|
pm.update(msg=bare_git._project.name)
|
||||||
|
|
||||||
if run_gc:
|
if run_gc:
|
||||||
bare_git.gc('--auto')
|
bare_git.gc(*gc_args)
|
||||||
else:
|
else:
|
||||||
bare_git.pack_refs()
|
bare_git.pack_refs(*pack_refs_args)
|
||||||
|
if backup_cruft:
|
||||||
|
self._backup_cruft(bare_git)
|
||||||
pm.end()
|
pm.end()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
cpu_count = os.cpu_count()
|
||||||
config = {'pack.threads': cpu_count // jobs if cpu_count > jobs else 1}
|
config = {'pack.threads': cpu_count // jobs if cpu_count > jobs else 1}
|
||||||
|
|
||||||
threads = set()
|
threads = set()
|
||||||
@ -663,15 +830,17 @@ later is required to fix a server side protocol bug.
|
|||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
if run_gc:
|
if run_gc:
|
||||||
bare_git.gc('--auto', config=config)
|
bare_git.gc(*gc_args, config=config)
|
||||||
else:
|
else:
|
||||||
bare_git.pack_refs(config=config)
|
bare_git.pack_refs(*pack_refs_args, config=config)
|
||||||
except GitError:
|
except GitError:
|
||||||
err_event.set()
|
err_event.set()
|
||||||
except Exception:
|
except Exception:
|
||||||
err_event.set()
|
err_event.set()
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
|
if backup_cruft:
|
||||||
|
self._backup_cruft(bare_git)
|
||||||
pm.finish(bare_git._project.name)
|
pm.finish(bare_git._project.name)
|
||||||
sem.release()
|
sem.release()
|
||||||
|
|
||||||
@ -688,28 +857,41 @@ later is required to fix a server side protocol bug.
|
|||||||
t.join()
|
t.join()
|
||||||
pm.end()
|
pm.end()
|
||||||
|
|
||||||
def _ReloadManifest(self, manifest_name=None, load_local_manifests=True):
|
def _ReloadManifest(self, manifest_name, manifest):
|
||||||
"""Reload the manfiest from the file specified by the |manifest_name|.
|
"""Reload the manfiest from the file specified by the |manifest_name|.
|
||||||
|
|
||||||
It unloads the manifest if |manifest_name| is None.
|
It unloads the manifest if |manifest_name| is None.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
manifest_name: Manifest file to be reloaded.
|
manifest_name: Manifest file to be reloaded.
|
||||||
load_local_manifests: Whether to load local manifests.
|
manifest: The manifest to use.
|
||||||
"""
|
"""
|
||||||
if manifest_name:
|
if manifest_name:
|
||||||
# Override calls Unload already
|
# Override calls Unload already
|
||||||
self.manifest.Override(manifest_name, load_local_manifests=load_local_manifests)
|
manifest.Override(manifest_name)
|
||||||
else:
|
else:
|
||||||
self.manifest.Unload()
|
manifest.Unload()
|
||||||
|
|
||||||
def UpdateProjectList(self, opt):
|
def UpdateProjectList(self, opt, manifest):
|
||||||
|
"""Update the cached projects list for |manifest|
|
||||||
|
|
||||||
|
In a multi-manifest checkout, each manifest has its own project.list.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt: Program options returned from optparse. See _Options().
|
||||||
|
manifest: The manifest to use.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
0: success
|
||||||
|
1: failure
|
||||||
|
"""
|
||||||
new_project_paths = []
|
new_project_paths = []
|
||||||
for project in self.GetProjects(None, missing_ok=True):
|
for project in self.GetProjects(None, missing_ok=True, manifest=manifest,
|
||||||
|
all_manifests=False):
|
||||||
if project.relpath:
|
if project.relpath:
|
||||||
new_project_paths.append(project.relpath)
|
new_project_paths.append(project.relpath)
|
||||||
file_name = 'project.list'
|
file_name = 'project.list'
|
||||||
file_path = os.path.join(self.manifest.subdir, file_name)
|
file_path = os.path.join(manifest.subdir, file_name)
|
||||||
old_project_paths = []
|
old_project_paths = []
|
||||||
|
|
||||||
if os.path.exists(file_path):
|
if os.path.exists(file_path):
|
||||||
@ -721,16 +903,16 @@ later is required to fix a server side protocol bug.
|
|||||||
continue
|
continue
|
||||||
if path not in new_project_paths:
|
if path not in new_project_paths:
|
||||||
# If the path has already been deleted, we don't need to do it
|
# If the path has already been deleted, we don't need to do it
|
||||||
gitdir = os.path.join(self.manifest.topdir, path, '.git')
|
gitdir = os.path.join(manifest.topdir, path, '.git')
|
||||||
if os.path.exists(gitdir):
|
if os.path.exists(gitdir):
|
||||||
project = Project(
|
project = Project(
|
||||||
manifest=self.manifest,
|
manifest=manifest,
|
||||||
name=path,
|
name=path,
|
||||||
remote=RemoteSpec('origin'),
|
remote=RemoteSpec('origin'),
|
||||||
gitdir=gitdir,
|
gitdir=gitdir,
|
||||||
objdir=gitdir,
|
objdir=gitdir,
|
||||||
use_git_worktrees=os.path.isfile(gitdir),
|
use_git_worktrees=os.path.isfile(gitdir),
|
||||||
worktree=os.path.join(self.manifest.topdir, path),
|
worktree=os.path.join(manifest.topdir, path),
|
||||||
relpath=path,
|
relpath=path,
|
||||||
revisionExpr='HEAD',
|
revisionExpr='HEAD',
|
||||||
revisionId=None,
|
revisionId=None,
|
||||||
@ -746,7 +928,7 @@ later is required to fix a server side protocol bug.
|
|||||||
fd.write('\n')
|
fd.write('\n')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def UpdateCopyLinkfileList(self):
|
def UpdateCopyLinkfileList(self, manifest):
|
||||||
"""Save all dests of copyfile and linkfile, and update them if needed.
|
"""Save all dests of copyfile and linkfile, and update them if needed.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -755,7 +937,8 @@ later is required to fix a server side protocol bug.
|
|||||||
new_paths = {}
|
new_paths = {}
|
||||||
new_linkfile_paths = []
|
new_linkfile_paths = []
|
||||||
new_copyfile_paths = []
|
new_copyfile_paths = []
|
||||||
for project in self.GetProjects(None, missing_ok=True):
|
for project in self.GetProjects(None, missing_ok=True,
|
||||||
|
manifest=manifest, all_manifests=False):
|
||||||
new_linkfile_paths.extend(x.dest for x in project.linkfiles)
|
new_linkfile_paths.extend(x.dest for x in project.linkfiles)
|
||||||
new_copyfile_paths.extend(x.dest for x in project.copyfiles)
|
new_copyfile_paths.extend(x.dest for x in project.copyfiles)
|
||||||
|
|
||||||
@ -765,7 +948,7 @@ later is required to fix a server side protocol bug.
|
|||||||
}
|
}
|
||||||
|
|
||||||
copylinkfile_name = 'copy-link-files.json'
|
copylinkfile_name = 'copy-link-files.json'
|
||||||
copylinkfile_path = os.path.join(self.manifest.subdir, copylinkfile_name)
|
copylinkfile_path = os.path.join(manifest.subdir, copylinkfile_name)
|
||||||
old_copylinkfile_paths = {}
|
old_copylinkfile_paths = {}
|
||||||
|
|
||||||
if os.path.exists(copylinkfile_path):
|
if os.path.exists(copylinkfile_path):
|
||||||
@ -796,13 +979,13 @@ later is required to fix a server side protocol bug.
|
|||||||
json.dump(new_paths, fp)
|
json.dump(new_paths, fp)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _SmartSyncSetup(self, opt, smart_sync_manifest_path):
|
def _SmartSyncSetup(self, opt, smart_sync_manifest_path, manifest):
|
||||||
if not self.manifest.manifest_server:
|
if not manifest.manifest_server:
|
||||||
print('error: cannot smart sync: no manifest server defined in '
|
print('error: cannot smart sync: no manifest server defined in '
|
||||||
'manifest', file=sys.stderr)
|
'manifest', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
manifest_server = self.manifest.manifest_server
|
manifest_server = manifest.manifest_server
|
||||||
if not opt.quiet:
|
if not opt.quiet:
|
||||||
print('Using manifest server %s' % manifest_server)
|
print('Using manifest server %s' % manifest_server)
|
||||||
|
|
||||||
@ -843,7 +1026,7 @@ later is required to fix a server side protocol bug.
|
|||||||
try:
|
try:
|
||||||
server = xmlrpc.client.Server(manifest_server, transport=transport)
|
server = xmlrpc.client.Server(manifest_server, transport=transport)
|
||||||
if opt.smart_sync:
|
if opt.smart_sync:
|
||||||
branch = self._GetBranch()
|
branch = self._GetBranch(manifest.manifestProject)
|
||||||
|
|
||||||
if 'SYNC_TARGET' in os.environ:
|
if 'SYNC_TARGET' in os.environ:
|
||||||
target = os.environ['SYNC_TARGET']
|
target = os.environ['SYNC_TARGET']
|
||||||
@ -869,36 +1052,68 @@ later is required to fix a server side protocol bug.
|
|||||||
% (smart_sync_manifest_path, e),
|
% (smart_sync_manifest_path, e),
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self._ReloadManifest(manifest_name)
|
self._ReloadManifest(manifest_name, manifest)
|
||||||
else:
|
else:
|
||||||
print('error: manifest server RPC call failed: %s' %
|
print('error: manifest server RPC call failed: %s' %
|
||||||
manifest_str, file=sys.stderr)
|
manifest_str, file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except (socket.error, IOError, xmlrpc.client.Fault) as e:
|
except (socket.error, IOError, xmlrpc.client.Fault) as e:
|
||||||
print('error: cannot connect to manifest server %s:\n%s'
|
print('error: cannot connect to manifest server %s:\n%s'
|
||||||
% (self.manifest.manifest_server, e), file=sys.stderr)
|
% (manifest.manifest_server, e), file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except xmlrpc.client.ProtocolError as e:
|
except xmlrpc.client.ProtocolError as e:
|
||||||
print('error: cannot connect to manifest server %s:\n%d %s'
|
print('error: cannot connect to manifest server %s:\n%d %s'
|
||||||
% (self.manifest.manifest_server, e.errcode, e.errmsg),
|
% (manifest.manifest_server, e.errcode, e.errmsg),
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
return manifest_name
|
return manifest_name
|
||||||
|
|
||||||
|
def _UpdateAllManifestProjects(self, opt, mp, manifest_name):
|
||||||
|
"""Fetch & update the local manifest project.
|
||||||
|
|
||||||
|
After syncing the manifest project, if the manifest has any sub manifests,
|
||||||
|
those are recursively processed.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt: Program options returned from optparse. See _Options().
|
||||||
|
mp: the manifestProject to query.
|
||||||
|
manifest_name: Manifest file to be reloaded.
|
||||||
|
"""
|
||||||
|
if not mp.standalone_manifest_url:
|
||||||
|
self._UpdateManifestProject(opt, mp, manifest_name)
|
||||||
|
|
||||||
|
if mp.manifest.submanifests:
|
||||||
|
for submanifest in mp.manifest.submanifests.values():
|
||||||
|
child = submanifest.repo_client.manifest
|
||||||
|
child.manifestProject.SyncWithPossibleInit(
|
||||||
|
submanifest,
|
||||||
|
current_branch_only=self._GetCurrentBranchOnly(opt, child),
|
||||||
|
verbose=opt.verbose,
|
||||||
|
tags=opt.tags,
|
||||||
|
git_event_log=self.git_event_log,
|
||||||
|
)
|
||||||
|
self._UpdateAllManifestProjects(opt, child.manifestProject, None)
|
||||||
|
|
||||||
def _UpdateManifestProject(self, opt, mp, manifest_name):
|
def _UpdateManifestProject(self, opt, mp, manifest_name):
|
||||||
"""Fetch & update the local manifest project."""
|
"""Fetch & update the local manifest project.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
opt: Program options returned from optparse. See _Options().
|
||||||
|
mp: the manifestProject to query.
|
||||||
|
manifest_name: Manifest file to be reloaded.
|
||||||
|
"""
|
||||||
if not opt.local_only:
|
if not opt.local_only:
|
||||||
start = time.time()
|
start = time.time()
|
||||||
success = mp.Sync_NetworkHalf(quiet=opt.quiet, verbose=opt.verbose,
|
success = mp.Sync_NetworkHalf(quiet=opt.quiet, verbose=opt.verbose,
|
||||||
current_branch_only=self._GetCurrentBranchOnly(opt),
|
current_branch_only=self._GetCurrentBranchOnly(opt, mp.manifest),
|
||||||
force_sync=opt.force_sync,
|
force_sync=opt.force_sync,
|
||||||
tags=opt.tags,
|
tags=opt.tags,
|
||||||
optimized_fetch=opt.optimized_fetch,
|
optimized_fetch=opt.optimized_fetch,
|
||||||
retry_fetches=opt.retry_fetches,
|
retry_fetches=opt.retry_fetches,
|
||||||
submodules=self.manifest.HasSubmodules,
|
submodules=mp.manifest.HasSubmodules,
|
||||||
clone_filter=self.manifest.CloneFilter,
|
clone_filter=mp.manifest.CloneFilter,
|
||||||
partial_clone_exclude=self.manifest.PartialCloneExclude)
|
partial_clone_exclude=mp.manifest.PartialCloneExclude)
|
||||||
finish = time.time()
|
finish = time.time()
|
||||||
self.event_log.AddSync(mp, event_log.TASK_SYNC_NETWORK,
|
self.event_log.AddSync(mp, event_log.TASK_SYNC_NETWORK,
|
||||||
start, finish, success)
|
start, finish, success)
|
||||||
@ -906,15 +1121,13 @@ later is required to fix a server side protocol bug.
|
|||||||
if mp.HasChanges:
|
if mp.HasChanges:
|
||||||
syncbuf = SyncBuffer(mp.config)
|
syncbuf = SyncBuffer(mp.config)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
mp.Sync_LocalHalf(syncbuf, submodules=self.manifest.HasSubmodules)
|
mp.Sync_LocalHalf(syncbuf, submodules=mp.manifest.HasSubmodules)
|
||||||
clean = syncbuf.Finish()
|
clean = syncbuf.Finish()
|
||||||
self.event_log.AddSync(mp, event_log.TASK_SYNC_LOCAL,
|
self.event_log.AddSync(mp, event_log.TASK_SYNC_LOCAL,
|
||||||
start, time.time(), clean)
|
start, time.time(), clean)
|
||||||
if not clean:
|
if not clean:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self._ReloadManifest(manifest_name)
|
self._ReloadManifest(manifest_name, mp.manifest)
|
||||||
if opt.jobs is None:
|
|
||||||
self.jobs = self.manifest.default.sync_j
|
|
||||||
|
|
||||||
def ValidateOptions(self, opt, args):
|
def ValidateOptions(self, opt, args):
|
||||||
if opt.force_broken:
|
if opt.force_broken:
|
||||||
@ -937,28 +1150,23 @@ later is required to fix a server side protocol bug.
|
|||||||
if opt.prune is None:
|
if opt.prune is None:
|
||||||
opt.prune = True
|
opt.prune = True
|
||||||
|
|
||||||
if self.manifest.is_multimanifest and not opt.this_manifest_only and args:
|
|
||||||
self.OptionParser.error('partial syncs must use --this-manifest-only')
|
|
||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
if opt.jobs:
|
manifest = self.outer_manifest
|
||||||
self.jobs = opt.jobs
|
if not opt.outer_manifest:
|
||||||
if self.jobs > 1:
|
manifest = self.manifest
|
||||||
soft_limit, _ = _rlimit_nofile()
|
|
||||||
self.jobs = min(self.jobs, (soft_limit - 5) // 3)
|
|
||||||
|
|
||||||
if opt.manifest_name:
|
if opt.manifest_name:
|
||||||
self.manifest.Override(opt.manifest_name)
|
manifest.Override(opt.manifest_name)
|
||||||
|
|
||||||
manifest_name = opt.manifest_name
|
manifest_name = opt.manifest_name
|
||||||
smart_sync_manifest_path = os.path.join(
|
smart_sync_manifest_path = os.path.join(
|
||||||
self.manifest.manifestProject.worktree, 'smart_sync_override.xml')
|
manifest.manifestProject.worktree, 'smart_sync_override.xml')
|
||||||
|
|
||||||
if opt.clone_bundle is None:
|
if opt.clone_bundle is None:
|
||||||
opt.clone_bundle = self.manifest.CloneBundle
|
opt.clone_bundle = manifest.CloneBundle
|
||||||
|
|
||||||
if opt.smart_sync or opt.smart_tag:
|
if opt.smart_sync or opt.smart_tag:
|
||||||
manifest_name = self._SmartSyncSetup(opt, smart_sync_manifest_path)
|
manifest_name = self._SmartSyncSetup(opt, smart_sync_manifest_path, manifest)
|
||||||
else:
|
else:
|
||||||
if os.path.isfile(smart_sync_manifest_path):
|
if os.path.isfile(smart_sync_manifest_path):
|
||||||
try:
|
try:
|
||||||
@ -969,7 +1177,7 @@ later is required to fix a server side protocol bug.
|
|||||||
|
|
||||||
err_event = multiprocessing.Event()
|
err_event = multiprocessing.Event()
|
||||||
|
|
||||||
rp = self.manifest.repoProject
|
rp = manifest.repoProject
|
||||||
rp.PreSync()
|
rp.PreSync()
|
||||||
cb = rp.CurrentBranch
|
cb = rp.CurrentBranch
|
||||||
if cb:
|
if cb:
|
||||||
@ -979,38 +1187,55 @@ later is required to fix a server side protocol bug.
|
|||||||
'receive updates; run `repo init --repo-rev=stable` to fix.',
|
'receive updates; run `repo init --repo-rev=stable` to fix.',
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
|
|
||||||
mp = self.manifest.manifestProject
|
for m in self.ManifestList(opt):
|
||||||
is_standalone_manifest = bool(mp.standalone_manifest_url)
|
if not m.manifestProject.standalone_manifest_url:
|
||||||
if not is_standalone_manifest:
|
m.manifestProject.PreSync()
|
||||||
mp.PreSync()
|
|
||||||
|
|
||||||
if opt.repo_upgraded:
|
if opt.repo_upgraded:
|
||||||
_PostRepoUpgrade(self.manifest, quiet=opt.quiet)
|
_PostRepoUpgrade(manifest, quiet=opt.quiet)
|
||||||
|
|
||||||
if not opt.mp_update:
|
mp = manifest.manifestProject
|
||||||
|
if opt.mp_update:
|
||||||
|
self._UpdateAllManifestProjects(opt, mp, manifest_name)
|
||||||
|
else:
|
||||||
print('Skipping update of local manifest project.')
|
print('Skipping update of local manifest project.')
|
||||||
elif not is_standalone_manifest:
|
|
||||||
self._UpdateManifestProject(opt, mp, manifest_name)
|
|
||||||
|
|
||||||
load_local_manifests = not self.manifest.HasLocalManifests
|
# Now that the manifests are up-to-date, setup the jobs value.
|
||||||
use_superproject = git_superproject.UseSuperproject(opt, self.manifest)
|
if opt.jobs is None:
|
||||||
if use_superproject and (self.manifest.IsMirror or self.manifest.IsArchive):
|
# User has not made a choice, so use the manifest settings.
|
||||||
# Don't use superproject, because we have no working tree.
|
opt.jobs = mp.default.sync_j
|
||||||
use_superproject = False
|
if opt.jobs is not None:
|
||||||
if opt.use_superproject is not None:
|
# Neither user nor manifest have made a choice.
|
||||||
print('Defaulting to no-use-superproject because there is no working tree.')
|
if opt.jobs_network is None:
|
||||||
superproject_logging_data = {
|
opt.jobs_network = opt.jobs
|
||||||
'superproject': use_superproject,
|
if opt.jobs_checkout is None:
|
||||||
'haslocalmanifests': bool(self.manifest.HasLocalManifests),
|
opt.jobs_checkout = opt.jobs
|
||||||
'hassuperprojecttag': bool(self.manifest.superproject),
|
# Setup defaults if jobs==0.
|
||||||
}
|
if not opt.jobs:
|
||||||
if use_superproject:
|
if not opt.jobs_network:
|
||||||
manifest_name = self._UpdateProjectsRevisionId(
|
opt.jobs_network = 1
|
||||||
opt, args, load_local_manifests, superproject_logging_data) or opt.manifest_name
|
if not opt.jobs_checkout:
|
||||||
|
opt.jobs_checkout = DEFAULT_LOCAL_JOBS
|
||||||
|
opt.jobs = os.cpu_count()
|
||||||
|
|
||||||
|
# Try to stay under user rlimit settings.
|
||||||
|
#
|
||||||
|
# Since each worker requires at 3 file descriptors to run `git fetch`, use
|
||||||
|
# that to scale down the number of jobs. Unfortunately there isn't an easy
|
||||||
|
# way to determine this reliably as systems change, but it was last measured
|
||||||
|
# by hand in 2011.
|
||||||
|
soft_limit, _ = _rlimit_nofile()
|
||||||
|
jobs_soft_limit = max(1, (soft_limit - 5) // 3)
|
||||||
|
opt.jobs = min(opt.jobs, jobs_soft_limit)
|
||||||
|
opt.jobs_network = min(opt.jobs_network, jobs_soft_limit)
|
||||||
|
opt.jobs_checkout = min(opt.jobs_checkout, jobs_soft_limit)
|
||||||
|
|
||||||
|
superproject_logging_data = {}
|
||||||
|
self._UpdateProjectsRevisionId(opt, args, superproject_logging_data,
|
||||||
|
manifest)
|
||||||
|
|
||||||
if self.gitc_manifest:
|
if self.gitc_manifest:
|
||||||
gitc_manifest_projects = self.GetProjects(args,
|
gitc_manifest_projects = self.GetProjects(args, missing_ok=True)
|
||||||
missing_ok=True)
|
|
||||||
gitc_projects = []
|
gitc_projects = []
|
||||||
opened_projects = []
|
opened_projects = []
|
||||||
for project in gitc_manifest_projects:
|
for project in gitc_manifest_projects:
|
||||||
@ -1029,7 +1254,7 @@ later is required to fix a server side protocol bug.
|
|||||||
if manifest_name:
|
if manifest_name:
|
||||||
manifest.Override(manifest_name)
|
manifest.Override(manifest_name)
|
||||||
else:
|
else:
|
||||||
manifest.Override(self.manifest.manifestFile)
|
manifest.Override(manifest.manifestFile)
|
||||||
gitc_utils.generate_gitc_manifest(self.gitc_manifest,
|
gitc_utils.generate_gitc_manifest(self.gitc_manifest,
|
||||||
manifest,
|
manifest,
|
||||||
gitc_projects)
|
gitc_projects)
|
||||||
@ -1039,26 +1264,30 @@ later is required to fix a server side protocol bug.
|
|||||||
# generate a new args list to represent the opened projects.
|
# generate a new args list to represent the opened projects.
|
||||||
# TODO: make this more reliable -- if there's a project name/path overlap,
|
# TODO: make this more reliable -- if there's a project name/path overlap,
|
||||||
# this may choose the wrong project.
|
# this may choose the wrong project.
|
||||||
args = [os.path.relpath(self.manifest.paths[path].worktree, os.getcwd())
|
args = [os.path.relpath(manifest.paths[path].worktree, os.getcwd())
|
||||||
for path in opened_projects]
|
for path in opened_projects]
|
||||||
if not args:
|
if not args:
|
||||||
return
|
return
|
||||||
|
|
||||||
all_projects = self.GetProjects(args,
|
all_projects = self.GetProjects(args,
|
||||||
missing_ok=True,
|
missing_ok=True,
|
||||||
submodules_ok=opt.fetch_submodules)
|
submodules_ok=opt.fetch_submodules,
|
||||||
|
manifest=manifest,
|
||||||
|
all_manifests=not opt.this_manifest_only)
|
||||||
|
|
||||||
err_network_sync = False
|
err_network_sync = False
|
||||||
err_update_projects = False
|
err_update_projects = False
|
||||||
|
err_update_linkfiles = False
|
||||||
|
|
||||||
self._fetch_times = _FetchTimes(self.manifest)
|
self._fetch_times = _FetchTimes(manifest)
|
||||||
if not opt.local_only:
|
if not opt.local_only:
|
||||||
with multiprocessing.Manager() as manager:
|
with multiprocessing.Manager() as manager:
|
||||||
with ssh.ProxyManager(manager) as ssh_proxy:
|
with ssh.ProxyManager(manager) as ssh_proxy:
|
||||||
# Initialize the socket dir once in the parent.
|
# Initialize the socket dir once in the parent.
|
||||||
ssh_proxy.sock()
|
ssh_proxy.sock()
|
||||||
all_projects = self._FetchMain(opt, args, all_projects, err_event,
|
result = self._FetchMain(opt, args, all_projects, err_event,
|
||||||
manifest_name, load_local_manifests,
|
ssh_proxy, manifest)
|
||||||
ssh_proxy)
|
all_projects = result.all_projects
|
||||||
|
|
||||||
if opt.network_only:
|
if opt.network_only:
|
||||||
return
|
return
|
||||||
@ -1074,18 +1303,19 @@ later is required to fix a server side protocol bug.
|
|||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if self.manifest.IsMirror or self.manifest.IsArchive:
|
for m in self.ManifestList(opt):
|
||||||
|
if m.IsMirror or m.IsArchive:
|
||||||
# bail out now, we have no working tree
|
# bail out now, we have no working tree
|
||||||
return
|
continue
|
||||||
|
|
||||||
if self.UpdateProjectList(opt):
|
if self.UpdateProjectList(opt, m):
|
||||||
err_event.set()
|
err_event.set()
|
||||||
err_update_projects = True
|
err_update_projects = True
|
||||||
if opt.fail_fast:
|
if opt.fail_fast:
|
||||||
print('\nerror: Local checkouts *not* updated.', file=sys.stderr)
|
print('\nerror: Local checkouts *not* updated.', file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
err_update_linkfiles = not self.UpdateCopyLinkfileList()
|
err_update_linkfiles = not self.UpdateCopyLinkfileList(m)
|
||||||
if err_update_linkfiles:
|
if err_update_linkfiles:
|
||||||
err_event.set()
|
err_event.set()
|
||||||
if opt.fail_fast:
|
if opt.fail_fast:
|
||||||
@ -1098,10 +1328,14 @@ later is required to fix a server side protocol bug.
|
|||||||
if err_checkout:
|
if err_checkout:
|
||||||
err_event.set()
|
err_event.set()
|
||||||
|
|
||||||
# If there's a notice that's supposed to print at the end of the sync, print
|
printed_notices = set()
|
||||||
# it now...
|
# If there's a notice that's supposed to print at the end of the sync,
|
||||||
if self.manifest.notice:
|
# print it now... But avoid printing duplicate messages, and preserve
|
||||||
print(self.manifest.notice)
|
# order.
|
||||||
|
for m in sorted(self.ManifestList(opt), key=lambda x: x.path_prefix):
|
||||||
|
if m.notice and m.notice not in printed_notices:
|
||||||
|
print(m.notice)
|
||||||
|
printed_notices.add(m.notice)
|
||||||
|
|
||||||
# If we saw an error, exit with code 1 so that other scripts can check.
|
# If we saw an error, exit with code 1 so that other scripts can check.
|
||||||
if err_event.is_set():
|
if err_event.is_set():
|
||||||
@ -1316,11 +1550,16 @@ class PersistentTransport(xmlrpc.client.Transport):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
p, u = xmlrpc.client.getparser()
|
p, u = xmlrpc.client.getparser()
|
||||||
while 1:
|
# Response should be fairly small, so read it all at once.
|
||||||
data = response.read(1024)
|
# This way we can show it to the user in case of error (e.g. HTML).
|
||||||
if not data:
|
data = response.read()
|
||||||
break
|
try:
|
||||||
p.feed(data)
|
p.feed(data)
|
||||||
|
except xml.parsers.expat.ExpatError as e:
|
||||||
|
raise IOError(
|
||||||
|
f'Parsing the manifest failed: {e}\n'
|
||||||
|
f'Please report this to your manifest server admin.\n'
|
||||||
|
f'Here is the full response:\n{data.decode("utf-8")}')
|
||||||
p.close()
|
p.close()
|
||||||
return u.close()
|
return u.close()
|
||||||
|
|
||||||
|
@ -78,6 +78,13 @@ added to the respective list of users, and emails are sent to any
|
|||||||
new users. Users passed as --reviewers must already be registered
|
new users. Users passed as --reviewers must already be registered
|
||||||
with the code review system, or the upload will fail.
|
with the code review system, or the upload will fail.
|
||||||
|
|
||||||
|
While most normal Gerrit options have dedicated command line options,
|
||||||
|
direct access to the Gerit options is available via --push-options.
|
||||||
|
This is useful when Gerrit has newer functionality that %prog doesn't
|
||||||
|
yet support, or doesn't have plans to support. See the Push Options
|
||||||
|
documentation for more details:
|
||||||
|
https://gerrit-review.googlesource.com/Documentation/user-upload.html#push_options
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
review.URL.autoupload:
|
review.URL.autoupload:
|
||||||
@ -190,6 +197,9 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
p.add_option('-w', '--wip',
|
p.add_option('-w', '--wip',
|
||||||
action='store_true', dest='wip', default=False,
|
action='store_true', dest='wip', default=False,
|
||||||
help='upload as a work-in-progress change')
|
help='upload as a work-in-progress change')
|
||||||
|
p.add_option('-r', '--ready',
|
||||||
|
action='store_true', default=False,
|
||||||
|
help='mark change as ready (clears work-in-progress setting)')
|
||||||
p.add_option('-o', '--push-option',
|
p.add_option('-o', '--push-option',
|
||||||
type='string', action='append', dest='push_options',
|
type='string', action='append', dest='push_options',
|
||||||
default=[],
|
default=[],
|
||||||
@ -204,6 +214,12 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
p.add_option('-y', '--yes',
|
p.add_option('-y', '--yes',
|
||||||
default=False, action='store_true',
|
default=False, action='store_true',
|
||||||
help='answer yes to all safe prompts')
|
help='answer yes to all safe prompts')
|
||||||
|
p.add_option('--ignore-untracked-files',
|
||||||
|
action='store_true', default=False,
|
||||||
|
help='ignore untracked files in the working copy')
|
||||||
|
p.add_option('--no-ignore-untracked-files',
|
||||||
|
dest='ignore_untracked_files', action='store_false',
|
||||||
|
help='always ask about untracked files in the working copy')
|
||||||
p.add_option('--no-cert-checks',
|
p.add_option('--no-cert-checks',
|
||||||
dest='validate_certs', action='store_false', default=True,
|
dest='validate_certs', action='store_false', default=True,
|
||||||
help='disable verifying ssl certs (unsafe)')
|
help='disable verifying ssl certs (unsafe)')
|
||||||
@ -246,7 +262,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
answer = sys.stdin.readline().strip().lower()
|
answer = sys.stdin.readline().strip().lower()
|
||||||
answer = answer in ('y', 'yes', '1', 'true', 't')
|
answer = answer in ('y', 'yes', '1', 'true', 't')
|
||||||
|
|
||||||
if answer:
|
if not opt.yes and answer:
|
||||||
if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
|
if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
|
||||||
answer = _ConfirmManyUploads()
|
answer = _ConfirmManyUploads()
|
||||||
|
|
||||||
@ -319,6 +335,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
if not todo:
|
if not todo:
|
||||||
_die("nothing uncommented for upload")
|
_die("nothing uncommented for upload")
|
||||||
|
|
||||||
|
if not opt.yes:
|
||||||
many_commits = False
|
many_commits = False
|
||||||
for branch in todo:
|
for branch in todo:
|
||||||
if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
|
if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD:
|
||||||
@ -370,6 +387,10 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
|
|
||||||
# Check if there are local changes that may have been forgotten
|
# Check if there are local changes that may have been forgotten
|
||||||
changes = branch.project.UncommitedFiles()
|
changes = branch.project.UncommitedFiles()
|
||||||
|
if opt.ignore_untracked_files:
|
||||||
|
untracked = set(branch.project.UntrackedFiles())
|
||||||
|
changes = [x for x in changes if x not in untracked]
|
||||||
|
|
||||||
if changes:
|
if changes:
|
||||||
key = 'review.%s.autoupload' % branch.project.remote.review
|
key = 'review.%s.autoupload' % branch.project.remote.review
|
||||||
answer = branch.project.config.GetBoolean(key)
|
answer = branch.project.config.GetBoolean(key)
|
||||||
@ -421,12 +442,6 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
labels = set(_ExpandCommaList(branch.project.config.GetString(key)))
|
labels = set(_ExpandCommaList(branch.project.config.GetString(key)))
|
||||||
for label in opt.labels:
|
for label in opt.labels:
|
||||||
labels.update(_ExpandCommaList(label))
|
labels.update(_ExpandCommaList(label))
|
||||||
# Basic sanity check on label syntax.
|
|
||||||
for label in labels:
|
|
||||||
if not re.match(r'^.+[+-][0-9]+$', label):
|
|
||||||
print('repo: error: invalid label syntax "%s": labels use forms '
|
|
||||||
'like CodeReview+1 or Verified-1' % (label,), file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Handle e-mail notifications.
|
# Handle e-mail notifications.
|
||||||
if opt.notify is False:
|
if opt.notify is False:
|
||||||
@ -461,6 +476,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
|
|||||||
private=opt.private,
|
private=opt.private,
|
||||||
notify=notify,
|
notify=notify,
|
||||||
wip=opt.wip,
|
wip=opt.wip,
|
||||||
|
ready=opt.ready,
|
||||||
dest_branch=destination,
|
dest_branch=destination,
|
||||||
validate_certs=opt.validate_certs,
|
validate_certs=opt.validate_certs,
|
||||||
push_options=opt.push_options)
|
push_options=opt.push_options)
|
||||||
|
@ -33,7 +33,7 @@ class Version(Command, MirrorSafeCommand):
|
|||||||
|
|
||||||
def Execute(self, opt, args):
|
def Execute(self, opt, args):
|
||||||
rp = self.manifest.repoProject
|
rp = self.manifest.repoProject
|
||||||
rem = rp.GetRemote(rp.remote.name)
|
rem = rp.GetRemote()
|
||||||
branch = rp.GetBranch('default')
|
branch = rp.GetBranch('default')
|
||||||
|
|
||||||
# These might not be the same. Report them both.
|
# These might not be the same. Report them both.
|
||||||
|
@ -24,7 +24,6 @@ from unittest import mock
|
|||||||
import git_superproject
|
import git_superproject
|
||||||
import git_trace2_event_log
|
import git_trace2_event_log
|
||||||
import manifest_xml
|
import manifest_xml
|
||||||
import platform_utils
|
|
||||||
from test_manifest_xml import sort_attributes
|
from test_manifest_xml import sort_attributes
|
||||||
|
|
||||||
|
|
||||||
@ -38,7 +37,8 @@ class SuperprojectTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up superproject every time."""
|
"""Set up superproject every time."""
|
||||||
self.tempdir = tempfile.mkdtemp(prefix='repo_tests')
|
self.tempdirobj = tempfile.TemporaryDirectory(prefix='repo_tests')
|
||||||
|
self.tempdir = self.tempdirobj.name
|
||||||
self.repodir = os.path.join(self.tempdir, '.repo')
|
self.repodir = os.path.join(self.tempdir, '.repo')
|
||||||
self.manifest_file = os.path.join(
|
self.manifest_file = os.path.join(
|
||||||
self.repodir, manifest_xml.MANIFEST_FILE_NAME)
|
self.repodir, manifest_xml.MANIFEST_FILE_NAME)
|
||||||
@ -75,7 +75,7 @@ class SuperprojectTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Tear down superproject every time."""
|
"""Tear down superproject every time."""
|
||||||
platform_utils.rmtree(self.tempdir)
|
self.tempdirobj.cleanup()
|
||||||
|
|
||||||
def getXmlManifest(self, data):
|
def getXmlManifest(self, data):
|
||||||
"""Helper to initialize a manifest for testing."""
|
"""Helper to initialize a manifest for testing."""
|
||||||
@ -312,9 +312,6 @@ class SuperprojectTestCase(unittest.TestCase):
|
|||||||
'<project groups="notdefault,platform-' + self.platform + '" '
|
'<project groups="notdefault,platform-' + self.platform + '" '
|
||||||
'name="platform/art" path="art" '
|
'name="platform/art" path="art" '
|
||||||
'revision="2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea" upstream="refs/heads/main"/>'
|
'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"/>'
|
'<superproject name="superproject"/>'
|
||||||
'</manifest>')
|
'</manifest>')
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
@ -92,7 +91,8 @@ class ManifestParseTestCase(unittest.TestCase):
|
|||||||
"""TestCase for parsing manifests."""
|
"""TestCase for parsing manifests."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.tempdir = tempfile.mkdtemp(prefix='repo_tests')
|
self.tempdirobj = tempfile.TemporaryDirectory(prefix='repo_tests')
|
||||||
|
self.tempdir = self.tempdirobj.name
|
||||||
self.repodir = os.path.join(self.tempdir, '.repo')
|
self.repodir = os.path.join(self.tempdir, '.repo')
|
||||||
self.manifest_dir = os.path.join(self.repodir, 'manifests')
|
self.manifest_dir = os.path.join(self.repodir, 'manifests')
|
||||||
self.manifest_file = os.path.join(
|
self.manifest_file = os.path.join(
|
||||||
@ -111,7 +111,7 @@ class ManifestParseTestCase(unittest.TestCase):
|
|||||||
""")
|
""")
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.tempdir, ignore_errors=True)
|
self.tempdirobj.cleanup()
|
||||||
|
|
||||||
def getXmlManifest(self, data):
|
def getXmlManifest(self, data):
|
||||||
"""Helper to initialize a manifest for testing."""
|
"""Helper to initialize a manifest for testing."""
|
||||||
@ -252,6 +252,37 @@ class XmlManifestTests(ManifestParseTestCase):
|
|||||||
'<manifest></manifest>')
|
'<manifest></manifest>')
|
||||||
self.assertEqual(manifest.ToDict(), {})
|
self.assertEqual(manifest.ToDict(), {})
|
||||||
|
|
||||||
|
def test_toxml_omit_local(self):
|
||||||
|
"""Does not include local_manifests projects when omit_local=True."""
|
||||||
|
manifest = self.getXmlManifest(
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?><manifest>'
|
||||||
|
'<remote name="a" fetch=".."/><default remote="a" revision="r"/>'
|
||||||
|
'<project name="p" groups="local::me"/>'
|
||||||
|
'<project name="q"/>'
|
||||||
|
'<project name="r" groups="keep"/>'
|
||||||
|
'</manifest>')
|
||||||
|
self.assertEqual(
|
||||||
|
manifest.ToXml(omit_local=True).toxml(),
|
||||||
|
'<?xml version="1.0" ?><manifest>'
|
||||||
|
'<remote name="a" fetch=".."/><default remote="a" revision="r"/>'
|
||||||
|
'<project name="q"/><project name="r" groups="keep"/></manifest>')
|
||||||
|
|
||||||
|
def test_toxml_with_local(self):
|
||||||
|
"""Does include local_manifests projects when omit_local=False."""
|
||||||
|
manifest = self.getXmlManifest(
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?><manifest>'
|
||||||
|
'<remote name="a" fetch=".."/><default remote="a" revision="r"/>'
|
||||||
|
'<project name="p" groups="local::me"/>'
|
||||||
|
'<project name="q"/>'
|
||||||
|
'<project name="r" groups="keep"/>'
|
||||||
|
'</manifest>')
|
||||||
|
self.assertEqual(
|
||||||
|
manifest.ToXml(omit_local=False).toxml(),
|
||||||
|
'<?xml version="1.0" ?><manifest>'
|
||||||
|
'<remote name="a" fetch=".."/><default remote="a" revision="r"/>'
|
||||||
|
'<project name="p" groups="local::me"/>'
|
||||||
|
'<project name="q"/><project name="r" groups="keep"/></manifest>')
|
||||||
|
|
||||||
def test_repo_hooks(self):
|
def test_repo_hooks(self):
|
||||||
"""Check repo-hooks settings."""
|
"""Check repo-hooks settings."""
|
||||||
manifest = self.getXmlManifest("""
|
manifest = self.getXmlManifest("""
|
||||||
@ -843,3 +874,27 @@ class ExtendProjectElementTests(ManifestParseTestCase):
|
|||||||
else:
|
else:
|
||||||
self.assertEqual(manifest.projects[0].relpath, 'bar')
|
self.assertEqual(manifest.projects[0].relpath, 'bar')
|
||||||
self.assertEqual(manifest.projects[1].relpath, 'y')
|
self.assertEqual(manifest.projects[1].relpath, 'y')
|
||||||
|
|
||||||
|
def test_extend_project_dest_branch(self):
|
||||||
|
manifest = self.getXmlManifest("""
|
||||||
|
<manifest>
|
||||||
|
<remote name="default-remote" fetch="http://localhost" />
|
||||||
|
<default remote="default-remote" revision="refs/heads/main" dest-branch="foo" />
|
||||||
|
<project name="myproject" />
|
||||||
|
<extend-project name="myproject" dest-branch="bar" />
|
||||||
|
</manifest>
|
||||||
|
""")
|
||||||
|
self.assertEqual(len(manifest.projects), 1)
|
||||||
|
self.assertEqual(manifest.projects[0].dest_branch, 'bar')
|
||||||
|
|
||||||
|
def test_extend_project_upstream(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" upstream="bar" />
|
||||||
|
</manifest>
|
||||||
|
""")
|
||||||
|
self.assertEqual(len(manifest.projects), 1)
|
||||||
|
self.assertEqual(manifest.projects[0].upstream, 'bar')
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
@ -32,11 +31,7 @@ import project
|
|||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def TempGitTree():
|
def TempGitTree():
|
||||||
"""Create a new empty git checkout for testing."""
|
"""Create a new empty git checkout for testing."""
|
||||||
# TODO(vapier): Convert this to tempfile.TemporaryDirectory once we drop
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
# Python 2 support entirely.
|
|
||||||
try:
|
|
||||||
tempdir = tempfile.mkdtemp(prefix='repo-tests')
|
|
||||||
|
|
||||||
# Tests need to assume, that main is default branch at init,
|
# Tests need to assume, that main is default branch at init,
|
||||||
# which is not supported in config until 2.28.
|
# which is not supported in config until 2.28.
|
||||||
cmd = ['git', 'init']
|
cmd = ['git', 'init']
|
||||||
@ -50,8 +45,6 @@ def TempGitTree():
|
|||||||
cmd += ['--template', templatedir]
|
cmd += ['--template', templatedir]
|
||||||
subprocess.check_call(cmd, cwd=tempdir)
|
subprocess.check_call(cmd, cwd=tempdir)
|
||||||
yield tempdir
|
yield tempdir
|
||||||
finally:
|
|
||||||
platform_utils.rmtree(tempdir)
|
|
||||||
|
|
||||||
|
|
||||||
class FakeProject(object):
|
class FakeProject(object):
|
||||||
@ -124,14 +117,15 @@ class CopyLinkTestCase(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.tempdir = tempfile.mkdtemp(prefix='repo_tests')
|
self.tempdirobj = tempfile.TemporaryDirectory(prefix='repo_tests')
|
||||||
|
self.tempdir = self.tempdirobj.name
|
||||||
self.topdir = os.path.join(self.tempdir, 'checkout')
|
self.topdir = os.path.join(self.tempdir, 'checkout')
|
||||||
self.worktree = os.path.join(self.topdir, 'git-project')
|
self.worktree = os.path.join(self.topdir, 'git-project')
|
||||||
os.makedirs(self.topdir)
|
os.makedirs(self.topdir)
|
||||||
os.makedirs(self.worktree)
|
os.makedirs(self.worktree)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.tempdir, ignore_errors=True)
|
self.tempdirobj.cleanup()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def touch(path):
|
def touch(path):
|
||||||
|
@ -42,4 +42,4 @@ def test_get_current_branch_only(use_superproject, cli_args, result):
|
|||||||
opts, _ = cmd.OptionParser.parse_args(cli_args)
|
opts, _ = cmd.OptionParser.parse_args(cli_args)
|
||||||
|
|
||||||
with mock.patch('git_superproject.UseSuperproject', return_value=use_superproject):
|
with mock.patch('git_superproject.UseSuperproject', return_value=use_superproject):
|
||||||
assert cmd._GetCurrentBranchOnly(opts) == result
|
assert cmd._GetCurrentBranchOnly(opts, cmd.manifest) == result
|
||||||
|
@ -14,11 +14,9 @@
|
|||||||
|
|
||||||
"""Unittests for the wrapper.py module."""
|
"""Unittests for the wrapper.py module."""
|
||||||
|
|
||||||
import contextlib
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
@ -26,22 +24,9 @@ from unittest import mock
|
|||||||
|
|
||||||
import git_command
|
import git_command
|
||||||
import main
|
import main
|
||||||
import platform_utils
|
|
||||||
import wrapper
|
import wrapper
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def TemporaryDirectory():
|
|
||||||
"""Create a new empty git checkout for testing."""
|
|
||||||
# TODO(vapier): Convert this to tempfile.TemporaryDirectory once we drop
|
|
||||||
# Python 2 support entirely.
|
|
||||||
try:
|
|
||||||
tempdir = tempfile.mkdtemp(prefix='repo-tests')
|
|
||||||
yield tempdir
|
|
||||||
finally:
|
|
||||||
platform_utils.rmtree(tempdir)
|
|
||||||
|
|
||||||
|
|
||||||
def fixture(*paths):
|
def fixture(*paths):
|
||||||
"""Return a path relative to tests/fixtures.
|
"""Return a path relative to tests/fixtures.
|
||||||
"""
|
"""
|
||||||
@ -336,19 +321,19 @@ class NeedSetupGnuPG(RepoWrapperTestCase):
|
|||||||
|
|
||||||
def test_missing_dir(self):
|
def test_missing_dir(self):
|
||||||
"""The ~/.repoconfig tree doesn't exist yet."""
|
"""The ~/.repoconfig tree doesn't exist yet."""
|
||||||
with TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
self.wrapper.home_dot_repo = os.path.join(tempdir, 'foo')
|
self.wrapper.home_dot_repo = os.path.join(tempdir, 'foo')
|
||||||
self.assertTrue(self.wrapper.NeedSetupGnuPG())
|
self.assertTrue(self.wrapper.NeedSetupGnuPG())
|
||||||
|
|
||||||
def test_missing_keyring(self):
|
def test_missing_keyring(self):
|
||||||
"""The keyring-version file doesn't exist yet."""
|
"""The keyring-version file doesn't exist yet."""
|
||||||
with TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
self.wrapper.home_dot_repo = tempdir
|
self.wrapper.home_dot_repo = tempdir
|
||||||
self.assertTrue(self.wrapper.NeedSetupGnuPG())
|
self.assertTrue(self.wrapper.NeedSetupGnuPG())
|
||||||
|
|
||||||
def test_empty_keyring(self):
|
def test_empty_keyring(self):
|
||||||
"""The keyring-version file exists, but is empty."""
|
"""The keyring-version file exists, but is empty."""
|
||||||
with TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
self.wrapper.home_dot_repo = tempdir
|
self.wrapper.home_dot_repo = tempdir
|
||||||
with open(os.path.join(tempdir, 'keyring-version'), 'w'):
|
with open(os.path.join(tempdir, 'keyring-version'), 'w'):
|
||||||
pass
|
pass
|
||||||
@ -356,7 +341,7 @@ class NeedSetupGnuPG(RepoWrapperTestCase):
|
|||||||
|
|
||||||
def test_old_keyring(self):
|
def test_old_keyring(self):
|
||||||
"""The keyring-version file exists, but it's old."""
|
"""The keyring-version file exists, but it's old."""
|
||||||
with TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
self.wrapper.home_dot_repo = tempdir
|
self.wrapper.home_dot_repo = tempdir
|
||||||
with open(os.path.join(tempdir, 'keyring-version'), 'w') as fp:
|
with open(os.path.join(tempdir, 'keyring-version'), 'w') as fp:
|
||||||
fp.write('1.0\n')
|
fp.write('1.0\n')
|
||||||
@ -364,7 +349,7 @@ class NeedSetupGnuPG(RepoWrapperTestCase):
|
|||||||
|
|
||||||
def test_new_keyring(self):
|
def test_new_keyring(self):
|
||||||
"""The keyring-version file exists, and is up-to-date."""
|
"""The keyring-version file exists, and is up-to-date."""
|
||||||
with TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
self.wrapper.home_dot_repo = tempdir
|
self.wrapper.home_dot_repo = tempdir
|
||||||
with open(os.path.join(tempdir, 'keyring-version'), 'w') as fp:
|
with open(os.path.join(tempdir, 'keyring-version'), 'w') as fp:
|
||||||
fp.write('1000.0\n')
|
fp.write('1000.0\n')
|
||||||
@ -376,7 +361,7 @@ class SetupGnuPG(RepoWrapperTestCase):
|
|||||||
|
|
||||||
def test_full(self):
|
def test_full(self):
|
||||||
"""Make sure it works completely."""
|
"""Make sure it works completely."""
|
||||||
with TemporaryDirectory() as tempdir:
|
with tempfile.TemporaryDirectory(prefix='repo-tests') as tempdir:
|
||||||
self.wrapper.home_dot_repo = tempdir
|
self.wrapper.home_dot_repo = tempdir
|
||||||
self.wrapper.gpg_dir = os.path.join(self.wrapper.home_dot_repo, 'gnupg')
|
self.wrapper.gpg_dir = os.path.join(self.wrapper.home_dot_repo, 'gnupg')
|
||||||
self.assertTrue(self.wrapper.SetupGnuPG(True))
|
self.assertTrue(self.wrapper.SetupGnuPG(True))
|
||||||
@ -426,7 +411,8 @@ class GitCheckoutTestCase(RepoWrapperTestCase):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
# Create a repo to operate on, but do it once per-class.
|
# Create a repo to operate on, but do it once per-class.
|
||||||
cls.GIT_DIR = tempfile.mkdtemp(prefix='repo-rev-tests')
|
cls.tempdirobj = tempfile.TemporaryDirectory(prefix='repo-rev-tests')
|
||||||
|
cls.GIT_DIR = cls.tempdirobj.name
|
||||||
run_git = wrapper.Wrapper().run_git
|
run_git = wrapper.Wrapper().run_git
|
||||||
|
|
||||||
remote = os.path.join(cls.GIT_DIR, 'remote')
|
remote = os.path.join(cls.GIT_DIR, 'remote')
|
||||||
@ -455,10 +441,10 @@ class GitCheckoutTestCase(RepoWrapperTestCase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tearDownClass(cls):
|
def tearDownClass(cls):
|
||||||
if not cls.GIT_DIR:
|
if not cls.tempdirobj:
|
||||||
return
|
return
|
||||||
|
|
||||||
shutil.rmtree(cls.GIT_DIR)
|
cls.tempdirobj.cleanup()
|
||||||
|
|
||||||
|
|
||||||
class ResolveRepoRev(GitCheckoutTestCase):
|
class ResolveRepoRev(GitCheckoutTestCase):
|
||||||
|
Reference in New Issue
Block a user