Skip to content

Instantly share code, notes, and snippets.

@glandium
Created December 2, 2016 05:00
Show Gist options
  • Save glandium/56a61454b2c3a1ad2cc269cc91292a56 to your computer and use it in GitHub Desktop.
Save glandium/56a61454b2c3a1ad2cc269cc91292a56 to your computer and use it in GitHub Desktop.
import atexit
import os
import shutil
import subprocess
from cinnabar.git import (
FastImport,
Git,
git_dir,
GitProcess,
sha1path,
)
from cinnabar.githg import (
GitCommit,
git_hash,
)
from cinnabar.helper import GitHgHelper
from cinnabar.util import (
init_logging,
one,
progress_iter,
)
from tempfile import mkdtemp
git_dir = os.path.abspath(git_dir)
clone = mkdtemp(prefix='.cinnabar.', dir=git_dir)
atexit.register(lambda: shutil.rmtree(clone))
init_logging()
GitProcess('clone', '--mirror', '--share', git_dir, clone,
stderr=open(os.devnull, 'w')).wait()
repo = 'https://github.com/glandium/gecko-dev'
print 'Fetching cinnabar metadata from %s' % repo
pwd = os.path.abspath('.')
os.chdir(clone)
GitProcess('fetch', repo, 'cinnabar').wait()
input = Git.resolve_ref('FETCH_HEAD')
ref = 'refs/cinnabar/metadata'
fast_import = FastImport()
fast_import.send_done()
fast_import._real_proc = GitProcess(
'fast-import', '--quiet', stdin=subprocess.PIPE,
config={'core.ignorecase': 'false'},
env={'GIT_DIR': git_dir})
fast_import.write('feature force\nfeature ls\nfeature done\n')
for line in Git.iter('ls-tree', '-r', input):
mode, typ, sha1, path = line.split()
Git._replace[path] = sha1
metadata = list(Git.iter('rev-parse', '%s^@' % input))
changesets = list(Git.iter('rev-parse', '%s^@' % metadata[0]))
for sha1 in Git._replace.itervalues():
if sha1 in changesets:
changesets.remove(sha1)
mark = fast_import.new_mark()
commit = GitCommit(metadata[0])
with fast_import.commit(
ref=ref,
parents=changesets,
mark=mark,
message=commit.body):
pass
changesets = mark
print 'Importing git2hg, manifests and replace metadata'
def refs():
yield metadata[3]
for sha1 in Git._replace.values():
yield sha1
for line in Git.iter('log', '%s^@' % metadata[1], '--format=%H^{tree}'):
yield line
GitProcess('pack-objects', '--revs', '--all-progress',
os.path.join(git_dir, 'objects', 'pack', 'pack'),
stdin=refs()).wait()
cs = set(Git.iter('rev-list', '%s^@' % metadata[0]))
marks = {}
mn = set()
for line in progress_iter('Finalizing %d manifests',
Git.iter('rev-list', '--reverse', '--parents',
'--topo-order', '%s^@' % metadata[1])):
parents = line.split()
sha1 = parents.pop(0)
try:
commit = GitCommit(sha1)
except:
print sha1
raise
mark = fast_import.new_mark()
with fast_import.commit(
ref=ref,
message=commit.body[:40],
parents=(marks[p] for p in parents),
mark=mark) as c:
c.filemodify('git', commit.body[40:], typ='tree')
c.filemodify('hg', commit.tree, typ='tree')
marks[sha1] = mark
mn.add(commit.body[:40])
manifests = fast_import.new_mark()
with fast_import.commit(
ref=ref,
parents=(marks[p] for p in Git.iter('rev-parse', '%s^@' % metadata[1])),
mark=manifests):
pass
hg2git = fast_import.new_mark()
with fast_import.commit(
ref=ref,
mark=hg2git) as c:
prev = None
for line in progress_iter('Importing %d hg2git metadata',
Git.iter('ls-tree', '-r', metadata[2])):
mode, typ, sha1, path = line.split()
node = path.replace('/', '')
if node in mn or sha1 in cs:
c.filemodify(path, sha1, typ='commit')
elif path.endswith('.meta'):
meta = Git.cat_file('blob', sha1)
data = Git.cat_file('blob', prev)
c.write('M %s inline %s\n' % (c.MODE['regular'], path[:-5]))
c.cmd_data('\1\n' + meta + '\1\n' + data)
c.filedelete(path)
else:
prev = sha1
c.filemodify(path, sha1)
with fast_import.commit(
ref=ref,
parents=(changesets, manifests, hg2git, metadata[3])):
for path, sha1 in Git._replace.iteritems():
c.filemodify(path, sha1, typ='commit')
for path, sha1 in Git._replace.iteritems():
fast_import.write('reset refs/cinnabar/replace/%s\nfrom %s\n\n'
% (path, sha1))
fast_import.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment