annotate mercurial/subrepo.py @ 10281:e7d3b509af8b

Introduce check-code.py check-code is a simple regex-based framework for checking our code and tests for common style and portability errors. Currently, it knows a fair amount about our Python and C style, and a little about common shell script portability problems.
author Matt Mackall <mpm@selenic.com>
date Mon, 25 Jan 2010 00:05:22 -0600
parents e898bc7810ad
children e768941f14c1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 # subrepo.py - sub-repository handling for Mercurial
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10251
diff changeset
6 # GNU General Public License version 2 or any later version.
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
8 import errno, os, re, xml.dom.minidom
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
9 from i18n import _
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
10 import config, util, node, error
9092
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
11 hg = None
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
12
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
13 nullstate = ('', '', 'empty')
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
15 def state(ctx):
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
16 p = config.config()
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
17 def read(f, sections=None, remap=None):
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
18 if f in ctx:
10174
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
19 p.parse(f, ctx[f].data(), sections, remap, read)
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
20 else:
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
21 raise util.Abort(_("subrepo spec file %s not found") % f)
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
22
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
23 if '.hgsub' in ctx:
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
24 read('.hgsub')
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
25
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
26 rev = {}
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27 if '.hgsubstate' in ctx:
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
28 try:
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29 for l in ctx['.hgsubstate'].data().splitlines():
9752
a22cdd5e56b7 subrepo: more robust split for .hgsubstate parsing
Matt Mackall <mpm@selenic.com>
parents: 9508
diff changeset
30 revision, path = l.split(" ", 1)
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
31 rev[path] = revision
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
32 except IOError, err:
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
33 if err.errno != errno.ENOENT:
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
34 raise
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
35
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
36 state = {}
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
37 for path, src in p[''].items():
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
38 kind = 'hg'
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
39 if src.startswith('['):
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
40 if ']' not in src:
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
41 raise util.Abort(_('missing ] in subrepo source'))
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
42 kind, src = src.split(']', 1)
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
43 kind = kind[1:]
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
44 state[path] = (src, rev.get(path, ''), kind)
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
45
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
46 return state
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
47
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
48 def writestate(repo, state):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
49 repo.wwrite('.hgsubstate',
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
50 ''.join(['%s %s\n' % (state[s][1], s)
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
51 for s in sorted(state)]), '')
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
52
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
53 def submerge(repo, wctx, mctx, actx):
10175
fc32b2fc468e subrepo: load from a context where the subrepo exists
Augie Fackler <durin42@gmail.com>
parents: 10174
diff changeset
54 # working context, merging context, ancestor context
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
55 if mctx == actx: # backwards?
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
56 actx = wctx.p1()
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
57 s1 = wctx.substate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
58 s2 = mctx.substate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
59 sa = actx.substate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
60 sm = {}
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
61
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
62 repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
63
9779
58a6f3f4d553 subrepo: add some debug output to submerge
Matt Mackall <mpm@selenic.com>
parents: 9752
diff changeset
64 def debug(s, msg, r=""):
58a6f3f4d553 subrepo: add some debug output to submerge
Matt Mackall <mpm@selenic.com>
parents: 9752
diff changeset
65 if r:
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
66 r = "%s:%s:%s" % r
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
67 repo.ui.debug(" subrepo %s: %s %s\n" % (s, msg, r))
9779
58a6f3f4d553 subrepo: add some debug output to submerge
Matt Mackall <mpm@selenic.com>
parents: 9752
diff changeset
68
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
69 for s, l in s1.items():
9783
ee00ef6f9be7 submerge: properly deal with overwrites
Matt Mackall <mpm@selenic.com>
parents: 9782
diff changeset
70 if wctx != actx and wctx.sub(s).dirty():
9780
1ee085511b89 subrepo: notice dirty subrepo states when merging
Matt Mackall <mpm@selenic.com>
parents: 9779
diff changeset
71 l = (l[0], l[1] + "+")
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
72 a = sa.get(s, nullstate)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
73 if s in s2:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
74 r = s2[s]
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
75 if l == r or r == a: # no change or local is newer
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
76 sm[s] = l
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
77 continue
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
78 elif l == a: # other side changed
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
79 debug(s, "other changed, get", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
80 wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
81 sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
82 elif l[0] != r[0]: # sources differ
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
83 if repo.ui.promptchoice(
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
84 _(' subrepository sources for %s differ\n'
8908
105343f9f744 Fix warning: Seen unexpected token "%"
Dongsheng Song <dongsheng.song@gmail.com>
parents: 8815
diff changeset
85 'use (l)ocal source (%s) or (r)emote source (%s)?')
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
86 % (s, l[0], r[0]),
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
87 (_('&Local'), _('&Remote')), 0):
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
88 debug(s, "prompt changed, get", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
89 wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
90 sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
91 elif l[1] == a[1]: # local side is unchanged
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
92 debug(s, "other side changed, get", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
93 wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
94 sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
95 else:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
96 debug(s, "both sides changed, merge with", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
97 wctx.sub(s).merge(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
98 sm[s] = l
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
99 elif l == a: # remote removed, local unchanged
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
100 debug(s, "remote removed, remove")
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
101 wctx.sub(s).remove()
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
102 else:
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
103 if repo.ui.promptchoice(
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
104 _(' local changed subrepository %s which remote removed\n'
8908
105343f9f744 Fix warning: Seen unexpected token "%"
Dongsheng Song <dongsheng.song@gmail.com>
parents: 8815
diff changeset
105 'use (c)hanged version or (d)elete?') % s,
9049
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
106 (_('&Changed'), _('&Delete')), 0):
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
107 debug(s, "prompt remove")
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
108 wctx.sub(s).remove()
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
109
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
110 for s, r in s2.items():
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
111 if s in s1:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
112 continue
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
113 elif s not in sa:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
114 debug(s, "remote added, get", r)
10175
fc32b2fc468e subrepo: load from a context where the subrepo exists
Augie Fackler <durin42@gmail.com>
parents: 10174
diff changeset
115 mctx.sub(s).get(r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
116 sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
117 elif r != sa[s]:
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
118 if repo.ui.promptchoice(
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
119 _(' remote changed subrepository %s which local removed\n'
8908
105343f9f744 Fix warning: Seen unexpected token "%"
Dongsheng Song <dongsheng.song@gmail.com>
parents: 8815
diff changeset
120 'use (c)hanged version or (d)elete?') % s,
9049
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
121 (_('&Changed'), _('&Delete')), 0) == 0:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
122 debug(s, "prompt recreate", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
123 wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
124 sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
125
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
126 # record merged .hgsubstate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
127 writestate(repo, sm)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
128
8815
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
129 def _abssource(repo, push=False):
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
130 if hasattr(repo, '_subparent'):
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
131 source = repo._subsource
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
132 if source.startswith('/') or '://' in source:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
133 return source
9186
f783bb979fb3 subrepo: use '/' for joining non-local paths
Matt Mackall <mpm@selenic.com>
parents: 8997
diff changeset
134 parent = _abssource(repo._subparent)
f783bb979fb3 subrepo: use '/' for joining non-local paths
Matt Mackall <mpm@selenic.com>
parents: 8997
diff changeset
135 if '://' in parent:
f783bb979fb3 subrepo: use '/' for joining non-local paths
Matt Mackall <mpm@selenic.com>
parents: 8997
diff changeset
136 if parent[-1] == '/':
f783bb979fb3 subrepo: use '/' for joining non-local paths
Matt Mackall <mpm@selenic.com>
parents: 8997
diff changeset
137 parent = parent[:-1]
f783bb979fb3 subrepo: use '/' for joining non-local paths
Matt Mackall <mpm@selenic.com>
parents: 8997
diff changeset
138 return parent + '/' + source
f783bb979fb3 subrepo: use '/' for joining non-local paths
Matt Mackall <mpm@selenic.com>
parents: 8997
diff changeset
139 return os.path.join(parent, repo._subsource)
8815
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
140 if push and repo.ui.config('paths', 'default-push'):
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
141 return repo.ui.config('paths', 'default-push', repo.root)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
142 return repo.ui.config('paths', 'default', repo.root)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
143
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
144 def subrepo(ctx, path):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
145 # subrepo inherently violates our import layering rules
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
146 # because it wants to make repo objects from deep inside the stack
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
147 # so we manually delay the circular imports to not break
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
148 # scripts that don't use our demand-loading
9092
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
149 global hg
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
150 import hg as h
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
151 hg = h
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
152
8997
70f5d3be5917 subrepo: audit subrepo paths
Matt Mackall <mpm@selenic.com>
parents: 8908
diff changeset
153 util.path_auditor(ctx._repo.root)(path)
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
154 state = ctx.substate.get(path, nullstate)
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
155 if state[2] not in types:
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
156 raise util.Abort(_('unknown subrepo type %s') % t)
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
157 return types[state[2]](ctx, path, state[:2])
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
158
10027
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
159 # subrepo classes need to implement the following methods:
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
160 # __init__(self, ctx, path, state)
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
161 # dirty(self): returns true if the dirstate of the subrepo
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
162 # does not match current stored state
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
163 # commit(self, text, user, date): commit the current changes
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
164 # to the subrepo with the given log message. Use given
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
165 # user and date if possible. Return the new state of the subrepo.
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
166 # remove(self): remove the subrepo (should verify the dirstate
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
167 # is not dirty first)
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
168 # get(self, state): run whatever commands are needed to put the
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
169 # subrepo into this state
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
170 # merge(self, state): merge currently-saved state with the new state.
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
171 # push(self, force): perform whatever action is analagous to 'hg push'
30d51a0df46c subrepo: document necessary methods for a subrepo class
Augie Fackler <durin42@gmail.com>
parents: 9783
diff changeset
172 # This may be a no-op on some systems.
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
173
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
174 class hgsubrepo(object):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
175 def __init__(self, ctx, path, state):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
176 self._path = path
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
177 self._state = state
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
178 r = ctx._repo
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
179 root = r.wjoin(path)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
180 if os.path.exists(os.path.join(root, '.hg')):
9092
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
181 self._repo = hg.repository(r.ui, root)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
182 else:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
183 util.makedirs(root)
9092
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
184 self._repo = hg.repository(r.ui, root, create=True)
10068
8f14f749f471 subrepo: add default path to new clones
Matt Mackall <mpm@selenic.com>
parents: 9783
diff changeset
185 f = file(os.path.join(root, '.hg', 'hgrc'), 'w')
8f14f749f471 subrepo: add default path to new clones
Matt Mackall <mpm@selenic.com>
parents: 9783
diff changeset
186 f.write('[paths]\ndefault = %s\n' % state[0])
8f14f749f471 subrepo: add default path to new clones
Matt Mackall <mpm@selenic.com>
parents: 9783
diff changeset
187 f.close()
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
188 self._repo._subparent = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
189 self._repo._subsource = state[0]
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
190
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
191 def dirty(self):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
192 r = self._state[1]
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
193 if r == '':
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
194 return True
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
195 w = self._repo[None]
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
196 if w.p1() != self._repo[r]: # version checked out changed
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
197 return True
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
198 return w.dirty() # working directory changed
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
199
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
200 def commit(self, text, user, date):
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
201 self._repo.ui.debug("committing subrepo %s\n" % self._path)
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
202 n = self._repo.commit(text, user, date)
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
203 if not n:
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
204 return self._repo['.'].hex() # different version checked out
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
205 return node.hex(n)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
206
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
207 def remove(self):
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
208 # we can't fully delete the repository as it may contain
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
209 # local-only history
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
210 self._repo.ui.note(_('removing subrepo %s\n') % self._path)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
211 hg.clean(self._repo, node.nullid, False)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
212
9507
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
213 def _get(self, state):
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
214 source, revision, kind = state
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
215 try:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
216 self._repo.lookup(revision)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
217 except error.RepoError:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
218 self._repo._subsource = source
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
219 self._repo.ui.status(_('pulling subrepo %s\n') % self._path)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
220 srcurl = _abssource(self._repo)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
221 other = hg.repository(self._repo.ui, srcurl)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
222 self._repo.pull(other)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
223
9507
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
224 def get(self, state):
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
225 self._get(state)
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
226 source, revision, kind = state
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
227 self._repo.ui.debug("getting subrepo %s\n" % self._path)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
228 hg.clean(self._repo, revision, False)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
229
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
230 def merge(self, state):
9507
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
231 self._get(state)
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
232 cur = self._repo['.']
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
233 dst = self._repo[state[1]]
10251
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
234 anc = dst.ancestor(cur)
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
235 if anc == cur:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
236 self._repo.ui.debug("updating subrepo %s\n" % self._path)
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
237 hg.update(self._repo, state[1])
10251
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
238 elif anc == dst:
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
239 self._repo.ui.debug("skipping subrepo %s\n" % self._path)
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
240 else:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
241 self._repo.ui.debug("merging subrepo %s\n" % self._path)
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
242 hg.merge(self._repo, state[1], remind=False)
8815
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
243
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
244 def push(self, force):
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
245 # push subrepos depth-first for coherent ordering
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
246 c = self._repo['']
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
247 subs = c.substate # only repos that are committed
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
248 for s in sorted(subs):
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
249 c.sub(s).push(force)
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
250
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
251 self._repo.ui.status(_('pushing subrepo %s\n') % self._path)
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
252 dsturl = _abssource(self._repo, True)
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
253 other = hg.repository(self._repo.ui, dsturl)
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
254 self._repo.push(other, force)
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
255
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
256 class svnsubrepo(object):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
257 def __init__(self, ctx, path, state):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
258 self._path = path
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
259 self._state = state
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
260 self._ctx = ctx
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
261 self._ui = ctx._repo.ui
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
262
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
263 def _svncommand(self, commands):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
264 cmd = ['svn'] + commands + [self._path]
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
265 cmd = [util.shellquote(arg) for arg in cmd]
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
266 cmd = util.quotecommand(' '.join(cmd))
10199
c2e2a5e6c36b subrepo: force en_US.UTF-8 locale when calling svn
Patrick Mezard <pmezard@gmail.com>
parents: 10197
diff changeset
267 env = dict(os.environ)
10271
9b38bec5dc29 subrepo: make svn use C locale for portability
Patrick Mezard <pmezard@gmail.com>
parents: 10264
diff changeset
268 # Avoid localized output, preserve current locale for everything else.
9b38bec5dc29 subrepo: make svn use C locale for portability
Patrick Mezard <pmezard@gmail.com>
parents: 10264
diff changeset
269 env['LC_MESSAGES'] = 'C'
10199
c2e2a5e6c36b subrepo: force en_US.UTF-8 locale when calling svn
Patrick Mezard <pmezard@gmail.com>
parents: 10197
diff changeset
270 write, read, err = util.popen3(cmd, env=env, newlines=True)
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
271 retdata = read.read()
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
272 err = err.read().strip()
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
273 if err:
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
274 raise util.Abort(err)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
275 return retdata
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
276
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
277 def _wcrev(self):
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
278 output = self._svncommand(['info', '--xml'])
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
279 doc = xml.dom.minidom.parseString(output)
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
280 entries = doc.getElementsByTagName('entry')
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
281 if not entries:
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
282 return 0
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
283 return int(entries[0].getAttribute('revision') or 0)
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
284
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
285 def _wcchanged(self):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
286 """Return (changes, extchanges) where changes is True
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
287 if the working directory was changed, and extchanges is
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
288 True if any of these changes concern an external entry.
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
289 """
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
290 output = self._svncommand(['status', '--xml'])
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
291 externals, changes = [], []
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
292 doc = xml.dom.minidom.parseString(output)
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
293 for e in doc.getElementsByTagName('entry'):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
294 s = e.getElementsByTagName('wc-status')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
295 if not s:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
296 continue
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
297 item = s[0].getAttribute('item')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
298 props = s[0].getAttribute('props')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
299 path = e.getAttribute('path')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
300 if item == 'external':
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
301 externals.append(path)
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
302 if (item not in ('', 'normal', 'unversioned', 'external')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
303 or props not in ('', 'none')):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
304 changes.append(path)
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
305 for path in changes:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
306 for ext in externals:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
307 if path == ext or path.startswith(ext + os.sep):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
308 return True, True
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
309 return bool(changes), False
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
310
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
311 def dirty(self):
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
312 if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
313 return False
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
314 return True
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
315
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
316 def commit(self, text, user, date):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
317 # user and date are out of our hands since svn is centralized
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
318 changed, extchanged = self._wcchanged()
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
319 if not changed:
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
320 return self._wcrev()
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
321 if extchanged:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
322 # Do not try to commit externals
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
323 raise util.Abort(_('cannot commit svn externals'))
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
324 commitinfo = self._svncommand(['commit', '-m', text])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
325 self._ui.status(commitinfo)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
326 newrev = re.search('Committed revision ([\d]+).', commitinfo)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
327 if not newrev:
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
328 raise util.Abort(commitinfo.splitlines()[-1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
329 newrev = newrev.groups()[0]
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
330 self._ui.status(self._svncommand(['update', '-r', newrev]))
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
331 return newrev
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
332
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
333 def remove(self):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
334 if self.dirty():
10227
192c39586787 subrepo: fix typo in help text
Jens Bäckman <jens.backman@gmail.com>
parents: 10199
diff changeset
335 self._repo.ui.warn(_('not removing repo %s because '
10183
572dd10fa308 subrepo: mark string for translation and fix case
Martin Geisler <mg@lazybytes.net>
parents: 10178
diff changeset
336 'it has changes.\n' % self._path))
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
337 return
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
338 self._repo.ui.note('removing subrepo %s\n' % self._path)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
339 shutil.rmtree(self._ctx.repo.join(self._path))
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
340
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
341 def get(self, state):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
342 status = self._svncommand(['checkout', state[0], '--revision', state[1]])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
343 if not re.search('Checked out revision [\d]+.', status):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
344 raise util.Abort(status.splitlines()[-1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
345 self._ui.status(status)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
346
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
347 def merge(self, state):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
348 old = int(self._state[1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
349 new = int(state[1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
350 if new > old:
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
351 self.get(state)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
352
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
353 def push(self, force):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
354 # nothing for svn
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
355 pass
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
356
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
357 types = {
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
358 'hg': hgsubrepo,
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
359 'svn': svnsubrepo,
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
360 }