init: Added --partial-clone-exclude option.

partial-clone-exclude option excludes projects during
partial clone. This is a comma-delimited project names
(from manifest.xml). This option is persisted and it
is used by the sync command.

A project that has been unparital'ed will remain unpartial if
that project's name is specified in the --partial-clone-exclude
option. The project name should match exactly.

Added
$ ./run_tests -v

Bug: [google internal] b/175712967
"I can't "unpartial" my androidx-main checkout"

$ rm -rf androidx-main/
$ mkdir androidx-main/
$ cd androidx-main/
$ repo_dev init -u https://android.googlesource.com/platform/manifest -b androidx-main --partial-clone --clone-filter=blob:limit=10M -m default.xml
$ repo_dev sync -c -j8

+ Verify a project is partial
$ cd frameworks/support/
$ git config -l | grep  'partial'

+ Unpartial a project.
$ /google/bin/releases/android/git_repack/git_unpartial

+ Verify project is unpartial
$ git config -l | grep  'partial'
$ cd ../..

+ Exclude the project from being unparial'ed after init and sync.
$ repo_dev init -u https://android.googlesource.com/platform/manifest -b androidx-main --partial-clone --clone-filter=blob:limit=10M --partial-clone-exclude="platform/frameworks/support,platform/frameworks/support-golden" -m default.xml

+ Verify project is unpartial
$ cd frameworks/support/
$ git config -l | grep  'partial'
$ cd ../..
$ repo_dev sync -c -j8
$ cd frameworks/support/
$ git config -l | grep  'partial'
$ cd ../..

+ Remove the project from exclude list and verify that project is partially cloned.
$ repo_dev init -u https://android.googlesource.com/platform/manifest -b androidx-main --partial-clone --clone-filter=blob:limit=10M --partial-clone-exclude= -m default.xml
$ repo_dev sync -c -j8
$ cd frameworks/support/
$ git config -l | grep  'partial'

Change-Id: Id5dba418eba1d3f54b54e826000406534c0ec196
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/303162
Reviewed-by: Mike Frysinger <vapier@google.com>
Tested-by: Raman Tenneti <rtenneti@google.com>
This commit is contained in:
Raman Tenneti 2021-04-12 20:57:25 -07:00
parent 49de8ef584
commit f32f243ff8
6 changed files with 42 additions and 21 deletions

View File

@ -157,6 +157,7 @@ User controlled settings are initialized when running `repo init`.
| repo.dissociate | `--dissociate` | Dissociate from any reference/mirrors after initial clone | | repo.dissociate | `--dissociate` | Dissociate from any reference/mirrors after initial clone |
| repo.mirror | `--mirror` | Checkout is a repo mirror | | repo.mirror | `--mirror` | Checkout is a repo mirror |
| repo.partialclone | `--partial-clone` | Create [partial git clones] | | repo.partialclone | `--partial-clone` | Create [partial git clones] |
| repo.partialcloneexclude | `--partial-clone-exclude` | Comma-delimited list of project names (not paths) to exclude while using [partial git clones] |
| repo.reference | `--reference` | Reference repo client checkout | | repo.reference | `--reference` | Reference repo client checkout |
| repo.submodules | `--submodules` | Sync git submodules | | repo.submodules | `--submodules` | Sync git submodules |
| repo.superproject | `--use-superproject` | Sync [superproject] | | repo.superproject | `--use-superproject` | Sync [superproject] |

View File

@ -589,6 +589,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
return self.manifestProject.config.GetString('repo.clonefilter') return self.manifestProject.config.GetString('repo.clonefilter')
return None return None
@property
def PartialCloneExclude(self):
exclude = self.manifest.manifestProject.config.GetString(
'repo.partialcloneexclude') or ''
return set(x.strip() for x in exclude.split(','))
@property @property
def IsMirror(self): def IsMirror(self):
return self.manifestProject.config.GetBoolean('repo.mirror') return self.manifestProject.config.GetBoolean('repo.mirror')

View File

@ -1050,7 +1050,8 @@ class Project(object):
retry_fetches=0, retry_fetches=0,
prune=False, prune=False,
submodules=False, submodules=False,
clone_filter=None): clone_filter=None,
partial_clone_exclude=None):
"""Perform only the network IO portion of the sync process. """Perform only the network IO portion of the sync process.
Local working directory/branch state is not affected. Local working directory/branch state is not affected.
""" """
@ -1087,6 +1088,10 @@ class Project(object):
if clone_bundle and os.path.exists(self.objdir): if clone_bundle and os.path.exists(self.objdir):
clone_bundle = False clone_bundle = False
if self.name in partial_clone_exclude:
clone_bundle = True
clone_filter = None
if is_new is None: if is_new is None:
is_new = not self.Exists is_new = not self.Exists
if is_new: if is_new:

4
repo
View File

@ -350,6 +350,10 @@ def InitParser(parser, gitc_init=False):
group.add_option('--no-partial-clone', action='store_false', group.add_option('--no-partial-clone', action='store_false',
help='disable use of partial clone (https://git-scm.com/' help='disable use of partial clone (https://git-scm.com/'
'docs/gitrepository-layout#_code_partialclone_code)') 'docs/gitrepository-layout#_code_partialclone_code)')
group.add_option('--partial-clone-exclude', action='store',
help='exclude the specified projects (a comma-delimited '
'project names) from partial clone (https://git-scm.com'
'/docs/gitrepository-layout#_code_partialclone_code)')
group.add_option('--clone-filter', action='store', default='blob:none', group.add_option('--clone-filter', action='store', default='blob:none',
help='filter for use with --partial-clone ' help='filter for use with --partial-clone '
'[default: %default]') '[default: %default]')

View File

@ -227,6 +227,9 @@ to update the working directory files.
else: else:
opt.clone_filter = None opt.clone_filter = None
if opt.partial_clone_exclude is not None:
m.config.SetString('repo.partialcloneexclude', opt.partial_clone_exclude)
if opt.clone_bundle is None: if opt.clone_bundle is None:
opt.clone_bundle = False if opt.partial_clone else True opt.clone_bundle = False if opt.partial_clone else True
else: else:
@ -242,7 +245,8 @@ to update the working directory files.
clone_bundle=opt.clone_bundle, clone_bundle=opt.clone_bundle,
current_branch_only=opt.current_branch_only, current_branch_only=opt.current_branch_only,
tags=opt.tags, submodules=opt.submodules, tags=opt.tags, submodules=opt.submodules,
clone_filter=opt.clone_filter): clone_filter=opt.clone_filter,
partial_clone_exclude=self.manifest.PartialCloneExclude):
r = m.GetRemote(m.remote.name) r = m.GetRemote(m.remote.name)
print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr) print('fatal: cannot obtain manifest %s' % r.url, file=sys.stderr)

View File

@ -348,7 +348,8 @@ later is required to fix a server side protocol bug.
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,
clone_filter=self.manifest.CloneFilter) clone_filter=self.manifest.CloneFilter,
partial_clone_exclude=self.manifest.PartialCloneExclude)
output = buf.getvalue() output = buf.getvalue()
if opt.verbose and output: if opt.verbose and output:
@ -517,7 +518,6 @@ later is required to fix a server side protocol bug.
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)) > 1):
if not opt.quiet: if not opt.quiet:
#pm.update(inc=0, msg='Shared project found')
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))
if git_require((2, 7, 0)): if git_require((2, 7, 0)):
@ -726,7 +726,8 @@ later is required to fix a server side protocol bug.
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=self.manifest.HasSubmodules,
clone_filter=self.manifest.CloneFilter) clone_filter=self.manifest.CloneFilter,
partial_clone_exclude=self.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)