##// END OF EJS Templates
largefiles: import whole modules instead of importing parts of them...
Mads Kiilerich -
r21084:70252bdf default
parent child Browse files
Show More
@@ -1,177 +1,176
1 # Copyright 2011 Fog Creek Software
1 # Copyright 2011 Fog Creek Software
2 #
2 #
3 # This software may be used and distributed according to the terms of the
3 # This software may be used and distributed according to the terms of the
4 # GNU General Public License version 2 or any later version.
4 # GNU General Public License version 2 or any later version.
5
5
6 import os
6 import os
7 import urllib2
7 import urllib2
8 import re
8 import re
9
9
10 from mercurial import error, httppeer, util, wireproto
10 from mercurial import error, httppeer, util, wireproto
11 from mercurial.wireproto import batchable, future
12 from mercurial.i18n import _
11 from mercurial.i18n import _
13
12
14 import lfutil
13 import lfutil
15
14
16 LARGEFILES_REQUIRED_MSG = ('\nThis repository uses the largefiles extension.'
15 LARGEFILES_REQUIRED_MSG = ('\nThis repository uses the largefiles extension.'
17 '\n\nPlease enable it in your Mercurial config '
16 '\n\nPlease enable it in your Mercurial config '
18 'file.\n')
17 'file.\n')
19
18
20 # these will all be replaced by largefiles.uisetup
19 # these will all be replaced by largefiles.uisetup
21 capabilitiesorig = None
20 capabilitiesorig = None
22 ssholdcallstream = None
21 ssholdcallstream = None
23 httpoldcallstream = None
22 httpoldcallstream = None
24
23
25 def putlfile(repo, proto, sha):
24 def putlfile(repo, proto, sha):
26 '''Put a largefile into a repository's local store and into the
25 '''Put a largefile into a repository's local store and into the
27 user cache.'''
26 user cache.'''
28 proto.redirect()
27 proto.redirect()
29
28
30 path = lfutil.storepath(repo, sha)
29 path = lfutil.storepath(repo, sha)
31 util.makedirs(os.path.dirname(path))
30 util.makedirs(os.path.dirname(path))
32 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
31 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode)
33
32
34 try:
33 try:
35 try:
34 try:
36 proto.getfile(tmpfp)
35 proto.getfile(tmpfp)
37 tmpfp._fp.seek(0)
36 tmpfp._fp.seek(0)
38 if sha != lfutil.hexsha1(tmpfp._fp):
37 if sha != lfutil.hexsha1(tmpfp._fp):
39 raise IOError(0, _('largefile contents do not match hash'))
38 raise IOError(0, _('largefile contents do not match hash'))
40 tmpfp.close()
39 tmpfp.close()
41 lfutil.linktousercache(repo, sha)
40 lfutil.linktousercache(repo, sha)
42 except IOError, e:
41 except IOError, e:
43 repo.ui.warn(_('largefiles: failed to put %s into store: %s\n') %
42 repo.ui.warn(_('largefiles: failed to put %s into store: %s\n') %
44 (sha, e.strerror))
43 (sha, e.strerror))
45 return wireproto.pushres(1)
44 return wireproto.pushres(1)
46 finally:
45 finally:
47 tmpfp.discard()
46 tmpfp.discard()
48
47
49 return wireproto.pushres(0)
48 return wireproto.pushres(0)
50
49
51 def getlfile(repo, proto, sha):
50 def getlfile(repo, proto, sha):
52 '''Retrieve a largefile from the repository-local cache or system
51 '''Retrieve a largefile from the repository-local cache or system
53 cache.'''
52 cache.'''
54 filename = lfutil.findfile(repo, sha)
53 filename = lfutil.findfile(repo, sha)
55 if not filename:
54 if not filename:
56 raise util.Abort(_('requested largefile %s not present in cache') % sha)
55 raise util.Abort(_('requested largefile %s not present in cache') % sha)
57 f = open(filename, 'rb')
56 f = open(filename, 'rb')
58 length = os.fstat(f.fileno())[6]
57 length = os.fstat(f.fileno())[6]
59
58
60 # Since we can't set an HTTP content-length header here, and
59 # Since we can't set an HTTP content-length header here, and
61 # Mercurial core provides no way to give the length of a streamres
60 # Mercurial core provides no way to give the length of a streamres
62 # (and reading the entire file into RAM would be ill-advised), we
61 # (and reading the entire file into RAM would be ill-advised), we
63 # just send the length on the first line of the response, like the
62 # just send the length on the first line of the response, like the
64 # ssh proto does for string responses.
63 # ssh proto does for string responses.
65 def generator():
64 def generator():
66 yield '%d\n' % length
65 yield '%d\n' % length
67 for chunk in util.filechunkiter(f):
66 for chunk in util.filechunkiter(f):
68 yield chunk
67 yield chunk
69 return wireproto.streamres(generator())
68 return wireproto.streamres(generator())
70
69
71 def statlfile(repo, proto, sha):
70 def statlfile(repo, proto, sha):
72 '''Return '2\n' if the largefile is missing, '0\n' if it seems to be in
71 '''Return '2\n' if the largefile is missing, '0\n' if it seems to be in
73 good condition.
72 good condition.
74
73
75 The value 1 is reserved for mismatched checksum, but that is too expensive
74 The value 1 is reserved for mismatched checksum, but that is too expensive
76 to be verified on every stat and must be caught be running 'hg verify'
75 to be verified on every stat and must be caught be running 'hg verify'
77 server side.'''
76 server side.'''
78 filename = lfutil.findfile(repo, sha)
77 filename = lfutil.findfile(repo, sha)
79 if not filename:
78 if not filename:
80 return '2\n'
79 return '2\n'
81 return '0\n'
80 return '0\n'
82
81
83 def wirereposetup(ui, repo):
82 def wirereposetup(ui, repo):
84 class lfileswirerepository(repo.__class__):
83 class lfileswirerepository(repo.__class__):
85 def putlfile(self, sha, fd):
84 def putlfile(self, sha, fd):
86 # unfortunately, httprepository._callpush tries to convert its
85 # unfortunately, httprepository._callpush tries to convert its
87 # input file-like into a bundle before sending it, so we can't use
86 # input file-like into a bundle before sending it, so we can't use
88 # it ...
87 # it ...
89 if issubclass(self.__class__, httppeer.httppeer):
88 if issubclass(self.__class__, httppeer.httppeer):
90 res = None
89 res = None
91 try:
90 try:
92 res = self._call('putlfile', data=fd, sha=sha,
91 res = self._call('putlfile', data=fd, sha=sha,
93 headers={'content-type':'application/mercurial-0.1'})
92 headers={'content-type':'application/mercurial-0.1'})
94 d, output = res.split('\n', 1)
93 d, output = res.split('\n', 1)
95 for l in output.splitlines(True):
94 for l in output.splitlines(True):
96 self.ui.warn(_('remote: '), l) # assume l ends with \n
95 self.ui.warn(_('remote: '), l) # assume l ends with \n
97 return int(d)
96 return int(d)
98 except (ValueError, urllib2.HTTPError):
97 except (ValueError, urllib2.HTTPError):
99 self.ui.warn(_('unexpected putlfile response: %r\n') % res)
98 self.ui.warn(_('unexpected putlfile response: %r\n') % res)
100 return 1
99 return 1
101 # ... but we can't use sshrepository._call because the data=
100 # ... but we can't use sshrepository._call because the data=
102 # argument won't get sent, and _callpush does exactly what we want
101 # argument won't get sent, and _callpush does exactly what we want
103 # in this case: send the data straight through
102 # in this case: send the data straight through
104 else:
103 else:
105 try:
104 try:
106 ret, output = self._callpush("putlfile", fd, sha=sha)
105 ret, output = self._callpush("putlfile", fd, sha=sha)
107 if ret == "":
106 if ret == "":
108 raise error.ResponseError(_('putlfile failed:'),
107 raise error.ResponseError(_('putlfile failed:'),
109 output)
108 output)
110 return int(ret)
109 return int(ret)
111 except IOError:
110 except IOError:
112 return 1
111 return 1
113 except ValueError:
112 except ValueError:
114 raise error.ResponseError(
113 raise error.ResponseError(
115 _('putlfile failed (unexpected response):'), ret)
114 _('putlfile failed (unexpected response):'), ret)
116
115
117 def getlfile(self, sha):
116 def getlfile(self, sha):
118 """returns an iterable with the chunks of the file with sha sha"""
117 """returns an iterable with the chunks of the file with sha sha"""
119 stream = self._callstream("getlfile", sha=sha)
118 stream = self._callstream("getlfile", sha=sha)
120 length = stream.readline()
119 length = stream.readline()
121 try:
120 try:
122 length = int(length)
121 length = int(length)
123 except ValueError:
122 except ValueError:
124 self._abort(error.ResponseError(_("unexpected response:"),
123 self._abort(error.ResponseError(_("unexpected response:"),
125 length))
124 length))
126
125
127 # SSH streams will block if reading more than length
126 # SSH streams will block if reading more than length
128 for chunk in util.filechunkiter(stream, 128 * 1024, length):
127 for chunk in util.filechunkiter(stream, 128 * 1024, length):
129 yield chunk
128 yield chunk
130 # HTTP streams must hit the end to process the last empty
129 # HTTP streams must hit the end to process the last empty
131 # chunk of Chunked-Encoding so the connection can be reused.
130 # chunk of Chunked-Encoding so the connection can be reused.
132 if issubclass(self.__class__, httppeer.httppeer):
131 if issubclass(self.__class__, httppeer.httppeer):
133 chunk = stream.read(1)
132 chunk = stream.read(1)
134 if chunk:
133 if chunk:
135 self._abort(error.ResponseError(_("unexpected response:"),
134 self._abort(error.ResponseError(_("unexpected response:"),
136 chunk))
135 chunk))
137
136
138 @batchable
137 @wireproto.batchable
139 def statlfile(self, sha):
138 def statlfile(self, sha):
140 f = future()
139 f = wireproto.future()
141 result = {'sha': sha}
140 result = {'sha': sha}
142 yield result, f
141 yield result, f
143 try:
142 try:
144 yield int(f.value)
143 yield int(f.value)
145 except (ValueError, urllib2.HTTPError):
144 except (ValueError, urllib2.HTTPError):
146 # If the server returns anything but an integer followed by a
145 # If the server returns anything but an integer followed by a
147 # newline, newline, it's not speaking our language; if we get
146 # newline, newline, it's not speaking our language; if we get
148 # an HTTP error, we can't be sure the largefile is present;
147 # an HTTP error, we can't be sure the largefile is present;
149 # either way, consider it missing.
148 # either way, consider it missing.
150 yield 2
149 yield 2
151
150
152 repo.__class__ = lfileswirerepository
151 repo.__class__ = lfileswirerepository
153
152
154 # advertise the largefiles=serve capability
153 # advertise the largefiles=serve capability
155 def capabilities(repo, proto):
154 def capabilities(repo, proto):
156 return capabilitiesorig(repo, proto) + ' largefiles=serve'
155 return capabilitiesorig(repo, proto) + ' largefiles=serve'
157
156
158 def heads(repo, proto):
157 def heads(repo, proto):
159 if lfutil.islfilesrepo(repo):
158 if lfutil.islfilesrepo(repo):
160 return wireproto.ooberror(LARGEFILES_REQUIRED_MSG)
159 return wireproto.ooberror(LARGEFILES_REQUIRED_MSG)
161 return wireproto.heads(repo, proto)
160 return wireproto.heads(repo, proto)
162
161
163 def sshrepocallstream(self, cmd, **args):
162 def sshrepocallstream(self, cmd, **args):
164 if cmd == 'heads' and self.capable('largefiles'):
163 if cmd == 'heads' and self.capable('largefiles'):
165 cmd = 'lheads'
164 cmd = 'lheads'
166 if cmd == 'batch' and self.capable('largefiles'):
165 if cmd == 'batch' and self.capable('largefiles'):
167 args['cmds'] = args['cmds'].replace('heads ', 'lheads ')
166 args['cmds'] = args['cmds'].replace('heads ', 'lheads ')
168 return ssholdcallstream(self, cmd, **args)
167 return ssholdcallstream(self, cmd, **args)
169
168
170 headsre = re.compile(r'(^|;)heads\b')
169 headsre = re.compile(r'(^|;)heads\b')
171
170
172 def httprepocallstream(self, cmd, **args):
171 def httprepocallstream(self, cmd, **args):
173 if cmd == 'heads' and self.capable('largefiles'):
172 if cmd == 'heads' and self.capable('largefiles'):
174 cmd = 'lheads'
173 cmd = 'lheads'
175 if cmd == 'batch' and self.capable('largefiles'):
174 if cmd == 'batch' and self.capable('largefiles'):
176 args['cmds'] = headsre.sub('lheads', args['cmds'])
175 args['cmds'] = headsre.sub('lheads', args['cmds'])
177 return httpoldcallstream(self, cmd, **args)
176 return httpoldcallstream(self, cmd, **args)
@@ -1,100 +1,99
1 # Copyright 2010-2011 Fog Creek Software
1 # Copyright 2010-2011 Fog Creek Software
2 # Copyright 2010-2011 Unity Technologies
2 # Copyright 2010-2011 Unity Technologies
3 #
3 #
4 # This software may be used and distributed according to the terms of the
4 # This software may be used and distributed according to the terms of the
5 # GNU General Public License version 2 or any later version.
5 # GNU General Public License version 2 or any later version.
6
6
7 '''remote largefile store; the base class for wirestore'''
7 '''remote largefile store; the base class for wirestore'''
8
8
9 import urllib2
9 import urllib2
10
10
11 from mercurial import util
11 from mercurial import util, wireproto
12 from mercurial.i18n import _
12 from mercurial.i18n import _
13 from mercurial.wireproto import remotebatch
14
13
15 import lfutil
14 import lfutil
16 import basestore
15 import basestore
17
16
18 class remotestore(basestore.basestore):
17 class remotestore(basestore.basestore):
19 '''a largefile store accessed over a network'''
18 '''a largefile store accessed over a network'''
20 def __init__(self, ui, repo, url):
19 def __init__(self, ui, repo, url):
21 super(remotestore, self).__init__(ui, repo, url)
20 super(remotestore, self).__init__(ui, repo, url)
22
21
23 def put(self, source, hash):
22 def put(self, source, hash):
24 if self.sendfile(source, hash):
23 if self.sendfile(source, hash):
25 raise util.Abort(
24 raise util.Abort(
26 _('remotestore: could not put %s to remote store %s')
25 _('remotestore: could not put %s to remote store %s')
27 % (source, util.hidepassword(self.url)))
26 % (source, util.hidepassword(self.url)))
28 self.ui.debug(
27 self.ui.debug(
29 _('remotestore: put %s to remote store %s\n')
28 _('remotestore: put %s to remote store %s\n')
30 % (source, util.hidepassword(self.url)))
29 % (source, util.hidepassword(self.url)))
31
30
32 def exists(self, hashes):
31 def exists(self, hashes):
33 return dict((h, s == 0) for (h, s) in # dict-from-generator
32 return dict((h, s == 0) for (h, s) in # dict-from-generator
34 self._stat(hashes).iteritems())
33 self._stat(hashes).iteritems())
35
34
36 def sendfile(self, filename, hash):
35 def sendfile(self, filename, hash):
37 self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash))
36 self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash))
38 fd = None
37 fd = None
39 try:
38 try:
40 try:
39 try:
41 fd = lfutil.httpsendfile(self.ui, filename)
40 fd = lfutil.httpsendfile(self.ui, filename)
42 except IOError, e:
41 except IOError, e:
43 raise util.Abort(
42 raise util.Abort(
44 _('remotestore: could not open file %s: %s')
43 _('remotestore: could not open file %s: %s')
45 % (filename, str(e)))
44 % (filename, str(e)))
46 return self._put(hash, fd)
45 return self._put(hash, fd)
47 finally:
46 finally:
48 if fd:
47 if fd:
49 fd.close()
48 fd.close()
50
49
51 def _getfile(self, tmpfile, filename, hash):
50 def _getfile(self, tmpfile, filename, hash):
52 try:
51 try:
53 chunks = self._get(hash)
52 chunks = self._get(hash)
54 except urllib2.HTTPError, e:
53 except urllib2.HTTPError, e:
55 # 401s get converted to util.Aborts; everything else is fine being
54 # 401s get converted to util.Aborts; everything else is fine being
56 # turned into a StoreError
55 # turned into a StoreError
57 raise basestore.StoreError(filename, hash, self.url, str(e))
56 raise basestore.StoreError(filename, hash, self.url, str(e))
58 except urllib2.URLError, e:
57 except urllib2.URLError, e:
59 # This usually indicates a connection problem, so don't
58 # This usually indicates a connection problem, so don't
60 # keep trying with the other files... they will probably
59 # keep trying with the other files... they will probably
61 # all fail too.
60 # all fail too.
62 raise util.Abort('%s: %s' %
61 raise util.Abort('%s: %s' %
63 (util.hidepassword(self.url), e.reason))
62 (util.hidepassword(self.url), e.reason))
64 except IOError, e:
63 except IOError, e:
65 raise basestore.StoreError(filename, hash, self.url, str(e))
64 raise basestore.StoreError(filename, hash, self.url, str(e))
66
65
67 return lfutil.copyandhash(chunks, tmpfile)
66 return lfutil.copyandhash(chunks, tmpfile)
68
67
69 def _verifyfile(self, cctx, cset, contents, standin, verified):
68 def _verifyfile(self, cctx, cset, contents, standin, verified):
70 filename = lfutil.splitstandin(standin)
69 filename = lfutil.splitstandin(standin)
71 if not filename:
70 if not filename:
72 return False
71 return False
73 fctx = cctx[standin]
72 fctx = cctx[standin]
74 key = (filename, fctx.filenode())
73 key = (filename, fctx.filenode())
75 if key in verified:
74 if key in verified:
76 return False
75 return False
77
76
78 verified.add(key)
77 verified.add(key)
79
78
80 expecthash = fctx.data()[0:40]
79 expecthash = fctx.data()[0:40]
81 stat = self._stat([expecthash])[expecthash]
80 stat = self._stat([expecthash])[expecthash]
82 if not stat:
81 if not stat:
83 return False
82 return False
84 elif stat == 1:
83 elif stat == 1:
85 self.ui.warn(
84 self.ui.warn(
86 _('changeset %s: %s: contents differ\n')
85 _('changeset %s: %s: contents differ\n')
87 % (cset, filename))
86 % (cset, filename))
88 return True # failed
87 return True # failed
89 elif stat == 2:
88 elif stat == 2:
90 self.ui.warn(
89 self.ui.warn(
91 _('changeset %s: %s missing\n')
90 _('changeset %s: %s missing\n')
92 % (cset, filename))
91 % (cset, filename))
93 return True # failed
92 return True # failed
94 else:
93 else:
95 raise RuntimeError('verify failed: unexpected response from '
94 raise RuntimeError('verify failed: unexpected response from '
96 'statlfile (%r)' % stat)
95 'statlfile (%r)' % stat)
97
96
98 def batch(self):
97 def batch(self):
99 '''Support for remote batching.'''
98 '''Support for remote batching.'''
100 return remotebatch(self)
99 return wireproto.remotebatch(self)
@@ -1,177 +1,177
1 # Copyright 2009-2010 Gregory P. Ward
1 # Copyright 2009-2010 Gregory P. Ward
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 # Copyright 2010-2011 Fog Creek Software
3 # Copyright 2010-2011 Fog Creek Software
4 # Copyright 2010-2011 Unity Technologies
4 # Copyright 2010-2011 Unity Technologies
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 '''setup for largefiles extension: uisetup'''
9 '''setup for largefiles extension: uisetup'''
10
10
11 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
11 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
12 httppeer, merge, scmutil, sshpeer, wireproto, revset
12 httppeer, merge, scmutil, sshpeer, wireproto, revset, subrepo
13 from mercurial.i18n import _
13 from mercurial.i18n import _
14 from mercurial.hgweb import hgweb_mod, webcommands
14 from mercurial.hgweb import hgweb_mod, webcommands
15 from mercurial.subrepo import hgsubrepo
16
15
17 import overrides
16 import overrides
18 import proto
17 import proto
19
18
20 def uisetup(ui):
19 def uisetup(ui):
21 # Disable auto-status for some commands which assume that all
20 # Disable auto-status for some commands which assume that all
22 # files in the result are under Mercurial's control
21 # files in the result are under Mercurial's control
23
22
24 entry = extensions.wrapcommand(commands.table, 'add',
23 entry = extensions.wrapcommand(commands.table, 'add',
25 overrides.overrideadd)
24 overrides.overrideadd)
26 addopt = [('', 'large', None, _('add as largefile')),
25 addopt = [('', 'large', None, _('add as largefile')),
27 ('', 'normal', None, _('add as normal file')),
26 ('', 'normal', None, _('add as normal file')),
28 ('', 'lfsize', '', _('add all files above this size '
27 ('', 'lfsize', '', _('add all files above this size '
29 '(in megabytes) as largefiles '
28 '(in megabytes) as largefiles '
30 '(default: 10)'))]
29 '(default: 10)'))]
31 entry[1].extend(addopt)
30 entry[1].extend(addopt)
32
31
33 # The scmutil function is called both by the (trivial) addremove command,
32 # The scmutil function is called both by the (trivial) addremove command,
34 # and in the process of handling commit -A (issue3542)
33 # and in the process of handling commit -A (issue3542)
35 entry = extensions.wrapfunction(scmutil, 'addremove',
34 entry = extensions.wrapfunction(scmutil, 'addremove',
36 overrides.scmutiladdremove)
35 overrides.scmutiladdremove)
37 entry = extensions.wrapcommand(commands.table, 'remove',
36 entry = extensions.wrapcommand(commands.table, 'remove',
38 overrides.overrideremove)
37 overrides.overrideremove)
39 entry = extensions.wrapcommand(commands.table, 'forget',
38 entry = extensions.wrapcommand(commands.table, 'forget',
40 overrides.overrideforget)
39 overrides.overrideforget)
41
40
42 # Subrepos call status function
41 # Subrepos call status function
43 entry = extensions.wrapcommand(commands.table, 'status',
42 entry = extensions.wrapcommand(commands.table, 'status',
44 overrides.overridestatus)
43 overrides.overridestatus)
45 entry = extensions.wrapfunction(hgsubrepo, 'status',
44 entry = extensions.wrapfunction(subrepo.hgsubrepo, 'status',
46 overrides.overridestatusfn)
45 overrides.overridestatusfn)
47
46
48 entry = extensions.wrapcommand(commands.table, 'log',
47 entry = extensions.wrapcommand(commands.table, 'log',
49 overrides.overridelog)
48 overrides.overridelog)
50 entry = extensions.wrapcommand(commands.table, 'rollback',
49 entry = extensions.wrapcommand(commands.table, 'rollback',
51 overrides.overriderollback)
50 overrides.overriderollback)
52 entry = extensions.wrapcommand(commands.table, 'verify',
51 entry = extensions.wrapcommand(commands.table, 'verify',
53 overrides.overrideverify)
52 overrides.overrideverify)
54
53
55 verifyopt = [('', 'large', None,
54 verifyopt = [('', 'large', None,
56 _('verify that all largefiles in current revision exists')),
55 _('verify that all largefiles in current revision exists')),
57 ('', 'lfa', None,
56 ('', 'lfa', None,
58 _('verify largefiles in all revisions, not just current')),
57 _('verify largefiles in all revisions, not just current')),
59 ('', 'lfc', None,
58 ('', 'lfc', None,
60 _('verify local largefile contents, not just existence'))]
59 _('verify local largefile contents, not just existence'))]
61 entry[1].extend(verifyopt)
60 entry[1].extend(verifyopt)
62
61
63 entry = extensions.wrapcommand(commands.table, 'debugstate',
62 entry = extensions.wrapcommand(commands.table, 'debugstate',
64 overrides.overridedebugstate)
63 overrides.overridedebugstate)
65 debugstateopt = [('', 'large', None, _('display largefiles dirstate'))]
64 debugstateopt = [('', 'large', None, _('display largefiles dirstate'))]
66 entry[1].extend(debugstateopt)
65 entry[1].extend(debugstateopt)
67
66
68 outgoing = lambda orgfunc, *arg, **kwargs: orgfunc(*arg, **kwargs)
67 outgoing = lambda orgfunc, *arg, **kwargs: orgfunc(*arg, **kwargs)
69 entry = extensions.wrapcommand(commands.table, 'outgoing', outgoing)
68 entry = extensions.wrapcommand(commands.table, 'outgoing', outgoing)
70 outgoingopt = [('', 'large', None, _('display outgoing largefiles'))]
69 outgoingopt = [('', 'large', None, _('display outgoing largefiles'))]
71 entry[1].extend(outgoingopt)
70 entry[1].extend(outgoingopt)
72 cmdutil.outgoinghooks.add('largefiles', overrides.outgoinghook)
71 cmdutil.outgoinghooks.add('largefiles', overrides.outgoinghook)
73 entry = extensions.wrapcommand(commands.table, 'summary',
72 entry = extensions.wrapcommand(commands.table, 'summary',
74 overrides.overridesummary)
73 overrides.overridesummary)
75 summaryopt = [('', 'large', None, _('display outgoing largefiles'))]
74 summaryopt = [('', 'large', None, _('display outgoing largefiles'))]
76 entry[1].extend(summaryopt)
75 entry[1].extend(summaryopt)
77 cmdutil.summaryremotehooks.add('largefiles', overrides.summaryremotehook)
76 cmdutil.summaryremotehooks.add('largefiles', overrides.summaryremotehook)
78
77
79 entry = extensions.wrapcommand(commands.table, 'update',
78 entry = extensions.wrapcommand(commands.table, 'update',
80 overrides.overrideupdate)
79 overrides.overrideupdate)
81 entry = extensions.wrapcommand(commands.table, 'pull',
80 entry = extensions.wrapcommand(commands.table, 'pull',
82 overrides.overridepull)
81 overrides.overridepull)
83 pullopt = [('', 'all-largefiles', None,
82 pullopt = [('', 'all-largefiles', None,
84 _('download all pulled versions of largefiles (DEPRECATED)')),
83 _('download all pulled versions of largefiles (DEPRECATED)')),
85 ('', 'lfrev', [],
84 ('', 'lfrev', [],
86 _('download largefiles for these revisions'), _('REV'))]
85 _('download largefiles for these revisions'), _('REV'))]
87 entry[1].extend(pullopt)
86 entry[1].extend(pullopt)
88 revset.symbols['pulled'] = overrides.pulledrevsetsymbol
87 revset.symbols['pulled'] = overrides.pulledrevsetsymbol
89
88
90 entry = extensions.wrapcommand(commands.table, 'clone',
89 entry = extensions.wrapcommand(commands.table, 'clone',
91 overrides.overrideclone)
90 overrides.overrideclone)
92 cloneopt = [('', 'all-largefiles', None,
91 cloneopt = [('', 'all-largefiles', None,
93 _('download all versions of all largefiles'))]
92 _('download all versions of all largefiles'))]
94 entry[1].extend(cloneopt)
93 entry[1].extend(cloneopt)
95 entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone)
94 entry = extensions.wrapfunction(hg, 'clone', overrides.hgclone)
96
95
97 entry = extensions.wrapcommand(commands.table, 'cat',
96 entry = extensions.wrapcommand(commands.table, 'cat',
98 overrides.overridecat)
97 overrides.overridecat)
99 entry = extensions.wrapfunction(merge, '_checkunknownfile',
98 entry = extensions.wrapfunction(merge, '_checkunknownfile',
100 overrides.overridecheckunknownfile)
99 overrides.overridecheckunknownfile)
101 entry = extensions.wrapfunction(merge, 'calculateupdates',
100 entry = extensions.wrapfunction(merge, 'calculateupdates',
102 overrides.overridecalculateupdates)
101 overrides.overridecalculateupdates)
103 entry = extensions.wrapfunction(filemerge, 'filemerge',
102 entry = extensions.wrapfunction(filemerge, 'filemerge',
104 overrides.overridefilemerge)
103 overrides.overridefilemerge)
105 entry = extensions.wrapfunction(cmdutil, 'copy',
104 entry = extensions.wrapfunction(cmdutil, 'copy',
106 overrides.overridecopy)
105 overrides.overridecopy)
107
106
108 # Summary calls dirty on the subrepos
107 # Summary calls dirty on the subrepos
109 entry = extensions.wrapfunction(hgsubrepo, 'dirty',
108 entry = extensions.wrapfunction(subrepo.hgsubrepo, 'dirty',
110 overrides.overridedirty)
109 overrides.overridedirty)
111
110
112 # Backout calls revert so we need to override both the command and the
111 # Backout calls revert so we need to override both the command and the
113 # function
112 # function
114 entry = extensions.wrapcommand(commands.table, 'revert',
113 entry = extensions.wrapcommand(commands.table, 'revert',
115 overrides.overriderevert)
114 overrides.overriderevert)
116 entry = extensions.wrapfunction(commands, 'revert',
115 entry = extensions.wrapfunction(commands, 'revert',
117 overrides.overriderevert)
116 overrides.overriderevert)
118
117
119 extensions.wrapfunction(hg, 'updaterepo', overrides.hgupdaterepo)
118 extensions.wrapfunction(hg, 'updaterepo', overrides.hgupdaterepo)
120 extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
119 extensions.wrapfunction(hg, 'merge', overrides.hgmerge)
121
120
122 extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
121 extensions.wrapfunction(archival, 'archive', overrides.overridearchive)
123 extensions.wrapfunction(hgsubrepo, 'archive', overrides.hgsubrepoarchive)
122 extensions.wrapfunction(subrepo.hgsubrepo, 'archive',
123 overrides.hgsubrepoarchive)
124 extensions.wrapfunction(cmdutil, 'bailifchanged',
124 extensions.wrapfunction(cmdutil, 'bailifchanged',
125 overrides.overridebailifchanged)
125 overrides.overridebailifchanged)
126
126
127 # create the new wireproto commands ...
127 # create the new wireproto commands ...
128 wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
128 wireproto.commands['putlfile'] = (proto.putlfile, 'sha')
129 wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
129 wireproto.commands['getlfile'] = (proto.getlfile, 'sha')
130 wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
130 wireproto.commands['statlfile'] = (proto.statlfile, 'sha')
131
131
132 # ... and wrap some existing ones
132 # ... and wrap some existing ones
133 wireproto.commands['capabilities'] = (proto.capabilities, '')
133 wireproto.commands['capabilities'] = (proto.capabilities, '')
134 wireproto.commands['heads'] = (proto.heads, '')
134 wireproto.commands['heads'] = (proto.heads, '')
135 wireproto.commands['lheads'] = (wireproto.heads, '')
135 wireproto.commands['lheads'] = (wireproto.heads, '')
136
136
137 # make putlfile behave the same as push and {get,stat}lfile behave
137 # make putlfile behave the same as push and {get,stat}lfile behave
138 # the same as pull w.r.t. permissions checks
138 # the same as pull w.r.t. permissions checks
139 hgweb_mod.perms['putlfile'] = 'push'
139 hgweb_mod.perms['putlfile'] = 'push'
140 hgweb_mod.perms['getlfile'] = 'pull'
140 hgweb_mod.perms['getlfile'] = 'pull'
141 hgweb_mod.perms['statlfile'] = 'pull'
141 hgweb_mod.perms['statlfile'] = 'pull'
142
142
143 extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
143 extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath)
144
144
145 # the hello wireproto command uses wireproto.capabilities, so it won't see
145 # the hello wireproto command uses wireproto.capabilities, so it won't see
146 # our largefiles capability unless we replace the actual function as well.
146 # our largefiles capability unless we replace the actual function as well.
147 proto.capabilitiesorig = wireproto.capabilities
147 proto.capabilitiesorig = wireproto.capabilities
148 wireproto.capabilities = proto.capabilities
148 wireproto.capabilities = proto.capabilities
149
149
150 # can't do this in reposetup because it needs to have happened before
150 # can't do this in reposetup because it needs to have happened before
151 # wirerepo.__init__ is called
151 # wirerepo.__init__ is called
152 proto.ssholdcallstream = sshpeer.sshpeer._callstream
152 proto.ssholdcallstream = sshpeer.sshpeer._callstream
153 proto.httpoldcallstream = httppeer.httppeer._callstream
153 proto.httpoldcallstream = httppeer.httppeer._callstream
154 sshpeer.sshpeer._callstream = proto.sshrepocallstream
154 sshpeer.sshpeer._callstream = proto.sshrepocallstream
155 httppeer.httppeer._callstream = proto.httprepocallstream
155 httppeer.httppeer._callstream = proto.httprepocallstream
156
156
157 # override some extensions' stuff as well
157 # override some extensions' stuff as well
158 for name, module in extensions.extensions():
158 for name, module in extensions.extensions():
159 if name == 'fetch':
159 if name == 'fetch':
160 extensions.wrapcommand(getattr(module, 'cmdtable'), 'fetch',
160 extensions.wrapcommand(getattr(module, 'cmdtable'), 'fetch',
161 overrides.overridefetch)
161 overrides.overridefetch)
162 if name == 'purge':
162 if name == 'purge':
163 extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
163 extensions.wrapcommand(getattr(module, 'cmdtable'), 'purge',
164 overrides.overridepurge)
164 overrides.overridepurge)
165 if name == 'rebase':
165 if name == 'rebase':
166 extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase',
166 extensions.wrapcommand(getattr(module, 'cmdtable'), 'rebase',
167 overrides.overriderebase)
167 overrides.overriderebase)
168 if name == 'transplant':
168 if name == 'transplant':
169 extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
169 extensions.wrapcommand(getattr(module, 'cmdtable'), 'transplant',
170 overrides.overridetransplant)
170 overrides.overridetransplant)
171 if name == 'convert':
171 if name == 'convert':
172 convcmd = getattr(module, 'convcmd')
172 convcmd = getattr(module, 'convcmd')
173 hgsink = getattr(convcmd, 'mercurial_sink')
173 hgsink = getattr(convcmd, 'mercurial_sink')
174 extensions.wrapfunction(hgsink, 'before',
174 extensions.wrapfunction(hgsink, 'before',
175 overrides.mercurialsinkbefore)
175 overrides.mercurialsinkbefore)
176 extensions.wrapfunction(hgsink, 'after',
176 extensions.wrapfunction(hgsink, 'after',
177 overrides.mercurialsinkafter)
177 overrides.mercurialsinkafter)
General Comments 0
You need to be logged in to leave comments. Login now