Commit b770b689 authored by Kirill Smelkov's avatar Kirill Smelkov

Make sure git will recognize *.git as repositories, even empty ones, after restore

On restore we were initializing refs/ and objects/ for repositories
obtained from backuped refs set, but this approach does not cover empty
repositories - e.g. repositories without any ref at all.

A frequent case for this is *.wiki.git in gitlab, and if we restore only
files for such repo, without empty refs/ and objects/ it would look like
restored ok, but any git-related operation on such repo will fail.

Fix it via making sure to create refs/ and objects/ the first time we
see a *.git while restoring files.

/cc @kazuhiko
parent 02c80d58
...@@ -655,6 +655,7 @@ def cmd_restore_(HEAD, restorespecv): ...@@ -655,6 +655,7 @@ def cmd_restore_(HEAD, restorespecv):
# files # files
lstree = xgit('ls-tree', '--full-tree', '-r', '-z', '--', HEAD, prefix, raw=True) lstree = xgit('ls-tree', '--full-tree', '-r', '-z', '--', HEAD, prefix, raw=True)
repos_seen = set() # dirs of *.git seen while restoring files
for _ in lstree.split('\0'): for _ in lstree.split('\0'):
if not _: if not _:
continue # last empty line after last \0 continue # last empty line after last \0
...@@ -666,6 +667,20 @@ def cmd_restore_(HEAD, restorespecv): ...@@ -666,6 +667,20 @@ def cmd_restore_(HEAD, restorespecv):
info('# file %s\t-> %s' % (prefix, filename)) info('# file %s\t-> %s' % (prefix, filename))
blob_to_file(sha1, mode, filename) blob_to_file(sha1, mode, filename)
# make sure git will recognize *.git as repo:
# - it should have refs/{heads,tags}/ and objects/pack/ inside.
#
# NOTE doing it while restoring files, because a repo could be
# empty - without refs at all, and thus next "git packs restore"
# step will not be run for it.
filedir = dirname(filename)
if filedir.endswith('.git') and not filedir in repos_seen:
info('# repo %s\t-> %s' % (prefix, filedir))
mkdir_p('%s/refs/heads' % filedir)
mkdir_p('%s/refs/tags' % filedir)
mkdir_p('%s/objects/pack' % filedir)
repos_seen.add(filedir)
# git packs # git packs
refs = set(_ for _ in backup_refs.keys() if _.startswith('%s/' % prefix)) refs = set(_ for _ in backup_refs.keys() if _.startswith('%s/' % prefix))
...@@ -675,11 +690,6 @@ def cmd_restore_(HEAD, restorespecv): ...@@ -675,11 +690,6 @@ def cmd_restore_(HEAD, restorespecv):
repopath = reprefix(prefix, dir_, repo) repopath = reprefix(prefix, dir_, repo)
info('# git %s\t-> %s' % (prefix, repopath)) info('# git %s\t-> %s' % (prefix, repopath))
# make sure git will recognize this dir as repo
# (refs could all be packed and thus no heads/ and tags/ dirs created on files restore)
mkdir_p('%s/refs/heads' % repopath)
mkdir_p('%s/refs/tags' % repopath)
# {} ref -> BackupRefSha1 for this repo # {} ref -> BackupRefSha1 for this repo
repo_refs = dict((reprefix(repo, 'refs', _), backup_refs[_]) repo_refs = dict((reprefix(repo, 'refs', _), backup_refs[_])
for _ in refs if _.startswith(repo)) for _ in refs if _.startswith(repo))
...@@ -693,7 +703,6 @@ def cmd_restore_(HEAD, restorespecv): ...@@ -693,7 +703,6 @@ def cmd_restore_(HEAD, restorespecv):
obj_recreate_from_commit(_.sha1_) obj_recreate_from_commit(_.sha1_)
# extract pack for that repo from big backup pack + decoded tags # extract pack for that repo from big backup pack + decoded tags
mkdir_p('%s/objects/pack' % repopath)
pack_argv = ['pack-objects', pack_argv = ['pack-objects',
'--revs', # include all objects referencable from input sha1 list '--revs', # include all objects referencable from input sha1 list
'--reuse-object', '--reuse-delta', '--delta-base-offset'] '--reuse-object', '--reuse-delta', '--delta-base-offset']
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment