Mercurial > hg
annotate hgext/largefiles/proto.py @ 25382:6084926366b9
summary: move the parents phase marker to commit line (issue4688)
The phase of the pending commit depends on the parent of the working directory
and on the phases.newcommit configuration.
First, this information rather depend on the commit line which describe the
pending commit.
Then, we only want to be advertised when the pending phase is going to be higher
than the default new commit phase.
So the format will change from
$ hg summary
parent: 2:ab91dfabc5ad
foo
parent: 3:24f1031ad244 tip
bar
branch: default
commit: 1 modified, 1 unknown, 1 unresolved (merge)
update: (current)
phases: 1 secret (secret)
to
parent: 2:ab91dfabc5ad
foo
parent: 3:24f1031ad244 tip
bar
branch: default
commit: 1 modified, 1 unknown, 1 unresolved (merge) (secret)
update: (current)
phases: 1 secret
author | Gilles Moris <gilles.moris@free.fr> |
---|---|
date | Fri, 29 May 2015 22:23:58 +0200 |
parents | bee00e0c2e45 |
children | 328739ea70c3 |
rev | line source |
---|---|
15168 | 1 # Copyright 2011 Fog Creek Software |
2 # | |
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. | |
5 | |
6 import os | |
7 import urllib2 | |
19917
cff331cbb5ee
largefiles: make the protocol hack for replacing heads with lheads more precise
Mads Kiilerich <madski@unity3d.com>
parents:
19009
diff
changeset
|
8 import re |
15168 | 9 |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
17127
diff
changeset
|
10 from mercurial import error, httppeer, util, wireproto |
15168 | 11 from mercurial.i18n import _ |
12 | |
13 import lfutil | |
14 | |
15255
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
15 LARGEFILES_REQUIRED_MSG = ('\nThis repository uses the largefiles extension.' |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
16 '\n\nPlease enable it in your Mercurial config ' |
7ab05d752405
largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents:
15252
diff
changeset
|
17 'file.\n') |
15168 | 18 |
18922
d2c4d37f7db5
largefiles: quiet (and document) undefined name errors (issue3886)
Bryan O'Sullivan <bryano@fb.com>
parents:
18488
diff
changeset
|
19 # these will all be replaced by largefiles.uisetup |
d2c4d37f7db5
largefiles: quiet (and document) undefined name errors (issue3886)
Bryan O'Sullivan <bryano@fb.com>
parents:
18488
diff
changeset
|
20 capabilitiesorig = None |
d2c4d37f7db5
largefiles: quiet (and document) undefined name errors (issue3886)
Bryan O'Sullivan <bryano@fb.com>
parents:
18488
diff
changeset
|
21 ssholdcallstream = None |
d2c4d37f7db5
largefiles: quiet (and document) undefined name errors (issue3886)
Bryan O'Sullivan <bryano@fb.com>
parents:
18488
diff
changeset
|
22 httpoldcallstream = None |
d2c4d37f7db5
largefiles: quiet (and document) undefined name errors (issue3886)
Bryan O'Sullivan <bryano@fb.com>
parents:
18488
diff
changeset
|
23 |
15168 | 24 def putlfile(repo, proto, sha): |
15317
41f371150ccb
largefiles: make the store primary, and the user cache secondary
Benjamin Pollack <benjamin@bitquabit.com>
parents:
15316
diff
changeset
|
25 '''Put a largefile into a repository's local store and into the |
41f371150ccb
largefiles: make the store primary, and the user cache secondary
Benjamin Pollack <benjamin@bitquabit.com>
parents:
15316
diff
changeset
|
26 user cache.''' |
15168 | 27 proto.redirect() |
15391
a5a6a9b7f3b9
largefiles: replace tempfile.NamedTemporaryFile with tempfile.mkstemp
Hao Lian <hao@fogcreek.com>
parents:
15317
diff
changeset
|
28 |
16594
5516fdf3fe24
largefiles: in putlfile, ensure tempfile's directory exists prior to creation
hlian
parents:
16247
diff
changeset
|
29 path = lfutil.storepath(repo, sha) |
5516fdf3fe24
largefiles: in putlfile, ensure tempfile's directory exists prior to creation
hlian
parents:
16247
diff
changeset
|
30 util.makedirs(os.path.dirname(path)) |
5516fdf3fe24
largefiles: in putlfile, ensure tempfile's directory exists prior to creation
hlian
parents:
16247
diff
changeset
|
31 tmpfp = util.atomictempfile(path, createmode=repo.store.createmode) |
5516fdf3fe24
largefiles: in putlfile, ensure tempfile's directory exists prior to creation
hlian
parents:
16247
diff
changeset
|
32 |
15168 | 33 try: |
25079
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
34 proto.getfile(tmpfp) |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
35 tmpfp._fp.seek(0) |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
36 if sha != lfutil.hexsha1(tmpfp._fp): |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
37 raise IOError(0, _('largefile contents do not match hash')) |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
38 tmpfp.close() |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
39 lfutil.linktousercache(repo, sha) |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
40 except IOError, e: |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
41 repo.ui.warn(_('largefiles: failed to put %s into store: %s\n') % |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
42 (sha, e.strerror)) |
bee00e0c2e45
largefiles: use try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
21084
diff
changeset
|
43 return wireproto.pushres(1) |
15168 | 44 finally: |
16155
1b2b42e866be
largefiles: respect store.createmode and avoid extra file copy
Martin Geisler <mg@aragost.com>
parents:
15778
diff
changeset
|
45 tmpfp.discard() |
15168 | 46 |
47 return wireproto.pushres(0) | |
48 | |
49 def getlfile(repo, proto, sha): | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
50 '''Retrieve a largefile from the repository-local cache or system |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
51 cache.''' |
15168 | 52 filename = lfutil.findfile(repo, sha) |
53 if not filename: | |
54 raise util.Abort(_('requested largefile %s not present in cache') % sha) | |
55 f = open(filename, 'rb') | |
56 length = os.fstat(f.fileno())[6] | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
57 |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
58 # Since we can't set an HTTP content-length header here, and |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
59 # Mercurial core provides no way to give the length of a streamres |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
60 # (and reading the entire file into RAM would be ill-advised), we |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
61 # just send the length on the first line of the response, like the |
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
62 # ssh proto does for string responses. |
15168 | 63 def generator(): |
64 yield '%d\n' % length | |
19009
07e40d589b64
largefiles: use filechunkiter for iterating largefile when serving getlfile
Mads Kiilerich <madski@unity3d.com>
parents:
19006
diff
changeset
|
65 for chunk in util.filechunkiter(f): |
15168 | 66 yield chunk |
67 return wireproto.streamres(generator()) | |
68 | |
69 def statlfile(repo, proto, sha): | |
18488
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
70 '''Return '2\n' if the largefile is missing, '0\n' if it seems to be in |
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
71 good condition. |
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
72 |
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
73 The value 1 is reserved for mismatched checksum, but that is too expensive |
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
74 to be verified on every stat and must be caught be running 'hg verify' |
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
75 server side.''' |
15168 | 76 filename = lfutil.findfile(repo, sha) |
77 if not filename: | |
78 return '2\n' | |
18488
a977b42df8b3
largefiles: don't verify largefile hashes on servers when processing statlfile
Mads Kiilerich <madski@unity3d.com>
parents:
18298
diff
changeset
|
79 return '0\n' |
15168 | 80 |
81 def wirereposetup(ui, repo): | |
82 class lfileswirerepository(repo.__class__): | |
83 def putlfile(self, sha, fd): | |
84 # unfortunately, httprepository._callpush tries to convert its | |
85 # input file-like into a bundle before sending it, so we can't use | |
86 # it ... | |
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
17127
diff
changeset
|
87 if issubclass(self.__class__, httppeer.httppeer): |
15778
f15c646bffc7
largefiles: display remote errors from putlfile (issue3123) (issue3149)
Kevin Gessner <kevin@fogcreek.com>
parents:
15391
diff
changeset
|
88 res = None |
15168 | 89 try: |
15778
f15c646bffc7
largefiles: display remote errors from putlfile (issue3123) (issue3149)
Kevin Gessner <kevin@fogcreek.com>
parents:
15391
diff
changeset
|
90 res = self._call('putlfile', data=fd, sha=sha, |
f15c646bffc7
largefiles: display remote errors from putlfile (issue3123) (issue3149)
Kevin Gessner <kevin@fogcreek.com>
parents:
15391
diff
changeset
|
91 headers={'content-type':'application/mercurial-0.1'}) |
f15c646bffc7
largefiles: display remote errors from putlfile (issue3123) (issue3149)
Kevin Gessner <kevin@fogcreek.com>
parents:
15391
diff
changeset
|
92 d, output = res.split('\n', 1) |
f15c646bffc7
largefiles: display remote errors from putlfile (issue3123) (issue3149)
Kevin Gessner <kevin@fogcreek.com>
parents:
15391
diff
changeset
|
93 for l in output.splitlines(True): |
19949
29f12a7a03ee
largefiles: don't add extra \n when displaying remote messages in putlfile
Mads Kiilerich <madski@unity3d.com>
parents:
19948
diff
changeset
|
94 self.ui.warn(_('remote: '), l) # assume l ends with \n |
15778
f15c646bffc7
largefiles: display remote errors from putlfile (issue3123) (issue3149)
Kevin Gessner <kevin@fogcreek.com>
parents:
15391
diff
changeset
|
95 return int(d) |
15168 | 96 except (ValueError, urllib2.HTTPError): |
19947
2a03faf8b5fe
largefiles: fix 'unexpected response' warning newlines
Mads Kiilerich <madski@unity3d.com>
parents:
19917
diff
changeset
|
97 self.ui.warn(_('unexpected putlfile response: %r\n') % res) |
15168 | 98 return 1 |
99 # ... but we can't use sshrepository._call because the data= | |
100 # argument won't get sent, and _callpush does exactly what we want | |
101 # in this case: send the data straight through | |
102 else: | |
103 try: | |
104 ret, output = self._callpush("putlfile", fd, sha=sha) | |
105 if ret == "": | |
106 raise error.ResponseError(_('putlfile failed:'), | |
107 output) | |
108 return int(ret) | |
109 except IOError: | |
110 return 1 | |
111 except ValueError: | |
112 raise error.ResponseError( | |
113 _('putlfile failed (unexpected response):'), ret) | |
114 | |
115 def getlfile(self, sha): | |
19004
6614e5e24e66
largefiles: move protocol conversion into getlfile and make it an iterable
Mads Kiilerich <madski@unity3d.com>
parents:
18922
diff
changeset
|
116 """returns an iterable with the chunks of the file with sha sha""" |
15168 | 117 stream = self._callstream("getlfile", sha=sha) |
118 length = stream.readline() | |
119 try: | |
120 length = int(length) | |
121 except ValueError: | |
15170
c1a4a3220711
largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents:
15168
diff
changeset
|
122 self._abort(error.ResponseError(_("unexpected response:"), |
c1a4a3220711
largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents:
15168
diff
changeset
|
123 length)) |
19004
6614e5e24e66
largefiles: move protocol conversion into getlfile and make it an iterable
Mads Kiilerich <madski@unity3d.com>
parents:
18922
diff
changeset
|
124 |
19005
1b84047e7d16
largefiles: drop limitreader, use filechunkiter limit
Mads Kiilerich <madski@unity3d.com>
parents:
19004
diff
changeset
|
125 # SSH streams will block if reading more than length |
1b84047e7d16
largefiles: drop limitreader, use filechunkiter limit
Mads Kiilerich <madski@unity3d.com>
parents:
19004
diff
changeset
|
126 for chunk in util.filechunkiter(stream, 128 * 1024, length): |
19004
6614e5e24e66
largefiles: move protocol conversion into getlfile and make it an iterable
Mads Kiilerich <madski@unity3d.com>
parents:
18922
diff
changeset
|
127 yield chunk |
19006
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
128 # HTTP streams must hit the end to process the last empty |
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
129 # chunk of Chunked-Encoding so the connection can be reused. |
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
130 if issubclass(self.__class__, httppeer.httppeer): |
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
131 chunk = stream.read(1) |
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
132 if chunk: |
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
133 self._abort(error.ResponseError(_("unexpected response:"), |
0b3b84222a2d
largefiles: getlfile must hit end of HTTP chunked streams to reuse connections
Mads Kiilerich <madski@unity3d.com>
parents:
19005
diff
changeset
|
134 chunk)) |
15168 | 135 |
21084
70252bdfd39c
largefiles: import whole modules instead of importing parts of them
Mads Kiilerich <madski@unity3d.com>
parents:
19949
diff
changeset
|
136 @wireproto.batchable |
15168 | 137 def statlfile(self, sha): |
21084
70252bdfd39c
largefiles: import whole modules instead of importing parts of them
Mads Kiilerich <madski@unity3d.com>
parents:
19949
diff
changeset
|
138 f = wireproto.future() |
17127
9e1616307c4c
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)
Na'Tosha Bard <natosha@unity3d.com>
parents:
16594
diff
changeset
|
139 result = {'sha': sha} |
9e1616307c4c
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)
Na'Tosha Bard <natosha@unity3d.com>
parents:
16594
diff
changeset
|
140 yield result, f |
15168 | 141 try: |
17127
9e1616307c4c
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)
Na'Tosha Bard <natosha@unity3d.com>
parents:
16594
diff
changeset
|
142 yield int(f.value) |
15168 | 143 except (ValueError, urllib2.HTTPError): |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
144 # If the server returns anything but an integer followed by a |
15168 | 145 # newline, newline, it's not speaking our language; if we get |
146 # an HTTP error, we can't be sure the largefile is present; | |
15252
6e809bb4f969
largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents:
15224
diff
changeset
|
147 # either way, consider it missing. |
17127
9e1616307c4c
largefiles: batch statlfile requests when pushing a largefiles repo (issue3386)
Na'Tosha Bard <natosha@unity3d.com>
parents:
16594
diff
changeset
|
148 yield 2 |
15168 | 149 |
150 repo.__class__ = lfileswirerepository | |
151 | |
152 # advertise the largefiles=serve capability | |
153 def capabilities(repo, proto): | |
16247
d87d9d8a8e03
largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents:
16155
diff
changeset
|
154 return capabilitiesorig(repo, proto) + ' largefiles=serve' |
15168 | 155 |
156 def heads(repo, proto): | |
157 if lfutil.islfilesrepo(repo): | |
15224
7c604d8c7e83
largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents:
15170
diff
changeset
|
158 return wireproto.ooberror(LARGEFILES_REQUIRED_MSG) |
15168 | 159 return wireproto.heads(repo, proto) |
160 | |
16247
d87d9d8a8e03
largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents:
16155
diff
changeset
|
161 def sshrepocallstream(self, cmd, **args): |
15168 | 162 if cmd == 'heads' and self.capable('largefiles'): |
163 cmd = 'lheads' | |
164 if cmd == 'batch' and self.capable('largefiles'): | |
165 args['cmds'] = args['cmds'].replace('heads ', 'lheads ') | |
16247
d87d9d8a8e03
largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents:
16155
diff
changeset
|
166 return ssholdcallstream(self, cmd, **args) |
15168 | 167 |
19917
cff331cbb5ee
largefiles: make the protocol hack for replacing heads with lheads more precise
Mads Kiilerich <madski@unity3d.com>
parents:
19009
diff
changeset
|
168 headsre = re.compile(r'(^|;)heads\b') |
cff331cbb5ee
largefiles: make the protocol hack for replacing heads with lheads more precise
Mads Kiilerich <madski@unity3d.com>
parents:
19009
diff
changeset
|
169 |
16247
d87d9d8a8e03
largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents:
16155
diff
changeset
|
170 def httprepocallstream(self, cmd, **args): |
15168 | 171 if cmd == 'heads' and self.capable('largefiles'): |
172 cmd = 'lheads' | |
173 if cmd == 'batch' and self.capable('largefiles'): | |
19917
cff331cbb5ee
largefiles: make the protocol hack for replacing heads with lheads more precise
Mads Kiilerich <madski@unity3d.com>
parents:
19009
diff
changeset
|
174 args['cmds'] = headsre.sub('lheads', args['cmds']) |
16247
d87d9d8a8e03
largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents:
16155
diff
changeset
|
175 return httpoldcallstream(self, cmd, **args) |