annotate hggit/hg2git.py @ 1116:bd1a01f98154

cleanup: wrap to 80 chars
author Sean Farley <sean@farley.io>
date Mon, 27 Nov 2017 19:05:08 -0500
parents 8ed6c0cae9b8
children 6141895a53c9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 # This file contains code dealing specifically with converting Mercurial
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 # repositories to Git repositories. Code in this file is meant to be a generic
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # library and should be usable outside the context of hg-git or an hg command.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 import os
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 import stat
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 import dulwich.objects as dulobjs
960
1b8d70c2bbfa hg2git: regularize mercurial imports
Siddharth Agarwal <sid0@fb.com>
parents: 894
diff changeset
9 from mercurial import (
1b8d70c2bbfa hg2git: regularize mercurial imports
Siddharth Agarwal <sid0@fb.com>
parents: 894
diff changeset
10 util as hgutil,
1b8d70c2bbfa hg2git: regularize mercurial imports
Siddharth Agarwal <sid0@fb.com>
parents: 894
diff changeset
11 )
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12
850
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
13 import compat
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 import util
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
15
1115
8ed6c0cae9b8 cleanup: add some blank lines
Sean Farley <sean@farley.io>
parents: 1063
diff changeset
16
671
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
17 def parse_subrepos(ctx):
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
18 sub = util.OrderedDict()
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
19 if '.hgsub' in ctx:
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
20 sub = util.parse_hgsub(ctx['.hgsub'].data().splitlines())
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
21 substate = util.OrderedDict()
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
22 if '.hgsubstate' in ctx:
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
23 substate = util.parse_hgsubstate(
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
24 ctx['.hgsubstate'].data().splitlines())
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
25 return sub, substate
71fb5dd678bc hg2git: move parse_subrepos to top level
Siddharth Agarwal <sid0@fb.com>
parents: 649
diff changeset
26
850
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
27
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
28 def audit_git_path(ui, path):
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
29 r"""Check for path components that case-fold to .git.
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
30
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
31 >>> class fakeui(object):
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
32 ... def configbool(*args):
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
33 ... return False
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
34 ... def warn(self, s):
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
35 ... print s
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
36 >>> u = fakeui()
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
37 >>> audit_git_path(u, 'foo/git~100/wat')
1116
bd1a01f98154 cleanup: wrap to 80 chars
Sean Farley <sean@farley.io>
parents: 1115
diff changeset
38 ... # doctest: +ELLIPSIS
bd1a01f98154 cleanup: wrap to 80 chars
Sean Farley <sean@farley.io>
parents: 1115
diff changeset
39 warning: path 'foo/git~100/wat' contains a potentially dangerous ...
850
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
40 It may not be legal to check out in Git.
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
41 It may also be rejected by some git server configurations.
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
42 <BLANKLINE>
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
43 >>> audit_git_path(u, u'foo/.gi\u200ct'.encode('utf-8'))
1116
bd1a01f98154 cleanup: wrap to 80 chars
Sean Farley <sean@farley.io>
parents: 1115
diff changeset
44 ... # doctest: +ELLIPSIS
bd1a01f98154 cleanup: wrap to 80 chars
Sean Farley <sean@farley.io>
parents: 1115
diff changeset
45 warning: path 'foo/.gi\xe2\x80\x8ct' contains a potentially dangerous ...
850
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
46 It may not be legal to check out in Git.
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
47 It may also be rejected by some git server configurations.
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
48 <BLANKLINE>
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
49 >>> audit_git_path(u, 'this/is/safe')
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
50 """
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
51 dangerous = False
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
52 for c in path.split(os.path.sep):
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
53 if compat.hfsignoreclean(c) == '.git':
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
54 dangerous = True
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
55 break
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
56 elif '~' in c:
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
57 base, tail = c.split('~', 1)
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
58 if tail.isdigit() and base.upper().startswith('GIT'):
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
59 dangerous = True
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
60 break
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
61 if dangerous:
1063
ae5759bf5bcd config: register git.blockdotgit
Kevin Bullock <kbullock@ringworld.org>
parents: 960
diff changeset
62 if compat.config(ui, 'bool', 'git', 'blockdotgit'):
850
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
63 raise hgutil.Abort(
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
64 ('Refusing to export likely-dangerous path %r' % path),
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
65 hint=("If you need to continue, read about CVE-2014-9390 and "
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
66 "then set '[git] blockdotgit = false' in your hgrc."))
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
67 ui.warn('warning: path %r contains a potentially dangerous path '
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
68 'component.\n'
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
69 'It may not be legal to check out in Git.\n'
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
70 'It may also be rejected by some git server configurations.\n'
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
71 % path)
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
72
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
73
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
74 class IncrementalChangesetExporter(object):
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75 """Incrementally export Mercurial changesets to Git trees.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
76
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
77 The purpose of this class is to facilitate Git tree export that is more
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
78 optimal than brute force.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
79
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
80 A "dumb" implementations of Mercurial to Git export would iterate over
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
81 every file present in a Mercurial changeset and would convert each to
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
82 a Git blob and then conditionally add it to a Git repository if it didn't
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
83 yet exist. This is suboptimal because the overhead associated with
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
84 obtaining every file's raw content and converting it to a Git blob is
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
85 not trivial!
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
86
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
87 This class works around the suboptimality of brute force export by
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
88 leveraging the information stored in Mercurial - the knowledge of what
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
89 changed between changesets - to only export Git objects corresponding to
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
90 changes in Mercurial. In the context of converting Mercurial repositories
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
91 to Git repositories, we only export objects Git (possibly) hasn't seen yet.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
92 This prevents a lot of redundant work and is thus faster.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
93
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
94 Callers instantiate an instance of this class against a mercurial.localrepo
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
95 instance. They then associate it with a specific changesets by calling
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
96 update_changeset(). On each call to update_changeset(), the instance
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
97 computes the difference between the current and new changesets and emits
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
98 Git objects that haven't yet been encountered during the lifetime of the
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
99 class instance. In other words, it expresses Mercurial changeset deltas in
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
100 terms of Git objects. Callers then (usually) take this set of Git objects
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
101 and add them to the Git repository.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
102
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
103 This class only emits Git blobs and trees, not commits.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
104
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
105 The tree calculation part of this class is essentially a reimplementation
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
106 of dulwich.index.commit_tree. However, since our implementation reuses
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
107 Tree instances and only recalculates SHA-1 when things change, we are
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
108 more efficient.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
109 """
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
110
709
5c7943ca051f hg2git: start incremental conversion from a known commit
Siddharth Agarwal <sid0@fb.com>
parents: 707
diff changeset
111 def __init__(self, hg_repo, start_ctx, git_store, git_commit):
5c7943ca051f hg2git: start incremental conversion from a known commit
Siddharth Agarwal <sid0@fb.com>
parents: 707
diff changeset
112 """Create an instance against a mercurial.localrepo.
5c7943ca051f hg2git: start incremental conversion from a known commit
Siddharth Agarwal <sid0@fb.com>
parents: 707
diff changeset
113
894
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
114 start_ctx: the context for a Mercurial commit that has a Git
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
115 equivalent, passed in as git_commit. The incremental
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
116 computation will be started from this commit.
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
117 git_store: the Git object store the commit comes from.
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
118
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
119 start_ctx can be repo[nullid], in which case git_commit should be None.
709
5c7943ca051f hg2git: start incremental conversion from a known commit
Siddharth Agarwal <sid0@fb.com>
parents: 707
diff changeset
120 """
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
121 self._hg = hg_repo
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
122
637
23d7caeed05a hg2git: store ctx instead of rev
Siddharth Agarwal <sid0@fb.com>
parents: 636
diff changeset
123 # Our current revision's context.
709
5c7943ca051f hg2git: start incremental conversion from a known commit
Siddharth Agarwal <sid0@fb.com>
parents: 707
diff changeset
124 self._ctx = start_ctx
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
125
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
126 # Path to dulwich.objects.Tree.
709
5c7943ca051f hg2git: start incremental conversion from a known commit
Siddharth Agarwal <sid0@fb.com>
parents: 707
diff changeset
127 self._init_dirs(git_store, git_commit)
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
128
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
129 # Mercurial file nodeid to Git blob SHA-1. Used to prevent redundant
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
130 # blob calculation.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
131 self._blob_cache = {}
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
132
707
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
133 def _init_dirs(self, store, commit):
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
134 """Initialize self._dirs for a Git object store and commit."""
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
135 self._dirs = {}
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
136 if commit is None:
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
137 return
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
138 dirkind = stat.S_IFDIR
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
139 # depth-first order, chosen arbitrarily
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
140 todo = [('', store[commit.tree])]
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
141 while todo:
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
142 path, tree = todo.pop()
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
143 self._dirs[path] = tree
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
144 for entry in tree.iteritems():
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
145 if entry.mode == dirkind:
710
623cb724c3d0 hg2git: in _init_dirs, store keys without leading '/' (issue103)
Siddharth Agarwal <sid0@fb.com>
parents: 709
diff changeset
146 if path == '':
623cb724c3d0 hg2git: in _init_dirs, store keys without leading '/' (issue103)
Siddharth Agarwal <sid0@fb.com>
parents: 709
diff changeset
147 newpath = entry.path
623cb724c3d0 hg2git: in _init_dirs, store keys without leading '/' (issue103)
Siddharth Agarwal <sid0@fb.com>
parents: 709
diff changeset
148 else:
623cb724c3d0 hg2git: in _init_dirs, store keys without leading '/' (issue103)
Siddharth Agarwal <sid0@fb.com>
parents: 709
diff changeset
149 newpath = path + '/' + entry.path
623cb724c3d0 hg2git: in _init_dirs, store keys without leading '/' (issue103)
Siddharth Agarwal <sid0@fb.com>
parents: 709
diff changeset
150 todo.append((newpath, store[entry.sha]))
707
d5facc1be5f8 hg2git: implement a method to initialize _dirs from a Git commit
Siddharth Agarwal <sid0@fb.com>
parents: 672
diff changeset
151
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
152 @property
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
153 def root_tree_sha(self):
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
154 """The SHA-1 of the root Git tree.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
155
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
156 This is needed to construct a Git commit object.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
157 """
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
158 return self._dirs[''].id
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
159
636
0ab89bd32c8e hg2git: rename ctx to newctx in update_changeset
Siddharth Agarwal <sid0@fb.com>
parents: 598
diff changeset
160 def update_changeset(self, newctx):
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
161 """Set the tree to track a new Mercurial changeset.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
162
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
163 This is a generator of 2-tuples. The first item in each tuple is a
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
164 dulwich object, either a Blob or a Tree. The second item is the
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
165 corresponding Mercurial nodeid for the item, if any. Only blobs will
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
166 have nodeids. Trees do not correspond to a specific nodeid, so it does
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
167 not make sense to emit a nodeid for them.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
168
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
169 When exporting trees from Mercurial, callers typically write the
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
170 returned dulwich object to the Git repo via the store's add_object().
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
171
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
172 Some emitted objects may already exist in the Git repository. This
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
173 class does not know about the Git repository, so it's up to the caller
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
174 to conditionally add the object, etc.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
175
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
176 Emitted objects are those that have changed since the last call to
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
177 update_changeset. If this is the first call to update_chanageset, all
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
178 objects in the tree are emitted.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
179 """
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
180 # Our general strategy is to accumulate dulwich.objects.Blob and
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
181 # dulwich.objects.Tree instances for the current Mercurial changeset.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
182 # We do this incremental by iterating over the Mercurial-reported
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
183 # changeset delta. We rely on the behavior of Mercurial to lazy
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
184 # calculate a Tree's SHA-1 when we modify it. This is critical to
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
185 # performance.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
186
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
187 # In theory we should be able to look at changectx.files(). This is
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
188 # *much* faster. However, it may not be accurate, especially with older
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
189 # repositories, which may not record things like deleted files
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
190 # explicitly in the manifest (which is where files() gets its data).
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
191 # The only reliable way to get the full set of changes is by looking at
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
192 # the full manifest. And, the easy way to compare two manifests is
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
193 # localrepo.status().
638
f828d82c35dc hg2git: call status on newctx, not newctx.rev()
Siddharth Agarwal <sid0@fb.com>
parents: 637
diff changeset
194 modified, added, removed = self._hg.status(self._ctx, newctx)[0:3]
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
195
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
196 # We track which directories/trees have modified in this update and we
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
197 # only export those.
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
198 dirty_trees = set()
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
199
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
200 subadded, subremoved = [], []
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
201
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
202 for s in modified, added, removed:
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
203 if '.hgsub' in s or '.hgsubstate' in s:
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
204 subadded, subremoved = self._handle_subrepos(newctx)
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
205 break
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
206
894
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
207 # We first process subrepo and file removals so we can prune dead
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
208 # trees.
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
209 for path in subremoved:
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
210 self._remove_path(path, dirty_trees)
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
211
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
212 for path in removed:
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
213 if path == '.hgsubstate' or path == '.hgsub':
649
53423381c540 hg2git: call _handle_subrepos when .hgsubstate is removed
Siddharth Agarwal <sid0@fb.com>
parents: 648
diff changeset
214 continue
53423381c540 hg2git: call _handle_subrepos when .hgsubstate is removed
Siddharth Agarwal <sid0@fb.com>
parents: 648
diff changeset
215
645
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
216 self._remove_path(path, dirty_trees)
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
217
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
218 for path, sha in subadded:
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
219 d = os.path.dirname(path)
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
220 tree = self._dirs.setdefault(d, dulobjs.Tree())
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
221 dirty_trees.add(d)
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
222 tree.add(os.path.basename(path), dulobjs.S_IFGITLINK, sha)
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
223
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
224 # For every file that changed or was added, we need to calculate the
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
225 # corresponding Git blob and its tree entry. We emit the blob
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
226 # immediately and update trees to be aware of its presence.
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
227 for path in set(modified) | set(added):
850
81c55f8629ba hg2git: audit path components during export (CVE-2014-9390)
Augie Fackler <raf@durin42.com>
parents: 710
diff changeset
228 audit_git_path(self._hg.ui, path)
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
229 if path == '.hgsubstate' or path == '.hgsub':
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
230 continue
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
231
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
232 d = os.path.dirname(path)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
233 tree = self._dirs.setdefault(d, dulobjs.Tree())
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
234 dirty_trees.add(d)
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
235
636
0ab89bd32c8e hg2git: rename ctx to newctx in update_changeset
Siddharth Agarwal <sid0@fb.com>
parents: 598
diff changeset
236 fctx = newctx[path]
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
237
894
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
238 func = IncrementalChangesetExporter.tree_entry
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
239 entry, blob = func(fctx, self._blob_cache)
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
240 if blob is not None:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
241 yield (blob, fctx.filenode())
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
242
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
243 tree.add(*entry)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
244
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
245 # Now that all the trees represent the current changeset, recalculate
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
246 # the tree IDs and emit them. Note that we wait until now to calculate
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
247 # tree SHA-1s. This is an important difference between us and
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
248 # dulwich.index.commit_tree(), which builds new Tree instances for each
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
249 # series of blobs.
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
250 for obj in self._populate_tree_entries(dirty_trees):
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
251 yield (obj, None)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
252
637
23d7caeed05a hg2git: store ctx instead of rev
Siddharth Agarwal <sid0@fb.com>
parents: 636
diff changeset
253 self._ctx = newctx
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
254
645
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
255 def _remove_path(self, path, dirty_trees):
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
256 """Remove a path (file or git link) from the current changeset.
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
257
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
258 If the tree containing this path is empty, it might be removed."""
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
259 d = os.path.dirname(path)
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
260 tree = self._dirs.get(d, dulobjs.Tree())
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
261
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
262 del tree[os.path.basename(path)]
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
263 dirty_trees.add(d)
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
264
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
265 # If removing this file made the tree empty, we should delete this
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
266 # tree. This could result in parent trees losing their only child
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
267 # and so on.
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
268 if not len(tree):
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
269 self._remove_tree(d)
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
270 else:
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
271 self._dirs[d] = tree
104f536be5c7 hg2git: factor out remove path logic into a separate function
Siddharth Agarwal <sid0@fb.com>
parents: 638
diff changeset
272
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
273 def _remove_tree(self, path):
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
274 """Remove a (presumably empty) tree from the current changeset.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
275
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
276 A now-empty tree may be the only child of its parent. So, we traverse
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
277 up the chain to the root tree, deleting any empty trees along the way.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
278 """
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
279 try:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
280 del self._dirs[path]
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
281 except KeyError:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
282 return
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
283
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
284 # Now we traverse up to the parent and delete any references.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
285 if path == '':
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
286 return
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
287
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
288 basename = os.path.basename(path)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
289 parent = os.path.dirname(path)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
290 while True:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
291 tree = self._dirs.get(parent, None)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
292
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
293 # No parent entry. Nothing to remove or update.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
294 if tree is None:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
295 return
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
296
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
297 try:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
298 del tree[basename]
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
299 except KeyError:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
300 return
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
301
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
302 if len(tree):
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
303 return
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
304
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
305 # The parent tree is empty. Se, we can delete it.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
306 del self._dirs[parent]
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
307
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
308 if parent == '':
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
309 return
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
310
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
311 basename = os.path.basename(parent)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
312 parent = os.path.dirname(parent)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
313
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
314 def _populate_tree_entries(self, dirty_trees):
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
315 self._dirs.setdefault('', dulobjs.Tree())
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
316
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
317 # Fill in missing directories.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
318 for path in self._dirs.keys():
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
319 parent = os.path.dirname(path)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
320
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
321 while parent != '':
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
322 parent_tree = self._dirs.get(parent, None)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
323
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
324 if parent_tree is not None:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
325 break
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
326
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
327 self._dirs[parent] = dulobjs.Tree()
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
328 parent = os.path.dirname(parent)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
329
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
330 for dirty in list(dirty_trees):
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
331 parent = os.path.dirname(dirty)
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
332
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
333 while parent != '':
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
334 if parent in dirty_trees:
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
335 break
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
336
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
337 dirty_trees.add(parent)
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
338 parent = os.path.dirname(parent)
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
339
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
340 # The root tree is always dirty but doesn't always get updated.
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
341 dirty_trees.add('')
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
342
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
343 # We only need to recalculate and export dirty trees.
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
344 for d in sorted(dirty_trees, key=len, reverse=True):
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
345 # Only happens for deleted directories.
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
346 try:
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
347 tree = self._dirs[d]
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
348 except KeyError:
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
349 continue
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
350
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
351 yield tree
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
352
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
353 if d == '':
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
354 continue
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
355
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
356 parent_tree = self._dirs[os.path.dirname(d)]
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
357
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
358 # Accessing the tree's ID is what triggers SHA-1 calculation and is
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
359 # the expensive part (at least if the tree has been modified since
598
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
360 # the last time we retrieved its ID). Also, assigning an entry to a
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
361 # tree (even if it already exists) invalidates the existing tree
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
362 # and incurs SHA-1 recalculation. So, it's in our interest to avoid
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
363 # invalidating trees. Since we only update the entries of dirty
792955be68dd Only export modified Git trees
Gregory Szorc <gregory.szorc@gmail.com>
parents: 596
diff changeset
364 # trees, this should hold true.
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
365 parent_tree[os.path.basename(d)] = (stat.S_IFDIR, tree.id)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
366
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
367 def _handle_subrepos(self, newctx):
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
368 sub, substate = parse_subrepos(self._ctx)
647
3ceacdd23abe hg2git: add 'new' prefix to _handle_subrepos variables
Siddharth Agarwal <sid0@fb.com>
parents: 646
diff changeset
369 newsub, newsubstate = parse_subrepos(newctx)
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
370
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
371 # For each path, the logic is described by the following table. 'no'
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
372 # stands for 'the subrepo doesn't exist', 'git' stands for 'git
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
373 # subrepo', and 'hg' stands for 'hg or other subrepo'.
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
374 #
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
375 # old new | action
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
376 # * git | link (1)
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
377 # git hg | delete (2)
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
378 # git no | delete (3)
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
379 #
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
380 # All other combinations are 'do nothing'.
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
381 #
894
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
382 # git links without corresponding submodule paths are stored as
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
383 # subrepos with a substate but without an entry in .hgsub.
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
384
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
385 # 'added' is both modified and added
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
386 added, removed = [], []
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
387
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
388 def isgit(sub, path):
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
389 return path not in sub or sub[path].startswith('[git]')
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
390
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
391 for path, sha in substate.iteritems():
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
392 if not isgit(sub, path):
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
393 # old = hg -- will be handled in next loop
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
394 continue
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
395 # old = git
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
396 if path not in newsubstate or not isgit(newsub, path):
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
397 # new = hg or no, case (2) or (3)
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
398 removed.append(path)
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
399
647
3ceacdd23abe hg2git: add 'new' prefix to _handle_subrepos variables
Siddharth Agarwal <sid0@fb.com>
parents: 646
diff changeset
400 for path, sha in newsubstate.iteritems():
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
401 if not isgit(newsub, path):
894
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
402 # new = hg or no; the only cases we care about are handled
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
403 # above
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
404 continue
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
405
648
bd63cdfbc1de hg2git: make _handle_subrepos worked in the removed case
Siddharth Agarwal <sid0@fb.com>
parents: 647
diff changeset
406 # case (1)
672
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
407 added.append((path, sha))
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
408
fbfa6353d96c hg2git: fix subrepo handling to be deterministic
Siddharth Agarwal <sid0@fb.com>
parents: 671
diff changeset
409 return added, removed
596
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
410
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
411 @staticmethod
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
412 def tree_entry(fctx, blob_cache):
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
413 """Compute a dulwich TreeEntry from a filectx.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
414
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
415 A side effect is the TreeEntry is stored in the passed cache.
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
416
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
417 Returns a 2-tuple of (dulwich.objects.TreeEntry, dulwich.objects.Blob).
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
418 """
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
419 blob_id = blob_cache.get(fctx.filenode(), None)
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
420 blob = None
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
421
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
422 if blob_id is None:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
423 blob = dulobjs.Blob.from_string(fctx.data())
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
424 blob_id = blob.id
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
425 blob_cache[fctx.filenode()] = blob_id
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
426
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
427 flags = fctx.flags()
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
428
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
429 if 'l' in flags:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
430 mode = 0120000
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
431 elif 'x' in flags:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
432 mode = 0100755
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
433 else:
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
434 mode = 0100644
d6b9c30a3e0f Export Git objects from incremental Mercurial changes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
435
894
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
436 return (dulobjs.TreeEntry(os.path.basename(fctx.path()), mode,
1959fd51ea12 hg2git: flake8 cleanup
Sean Farley <sean@farley.io>
parents: 850
diff changeset
437 blob_id), blob)