Mercurial > hg
annotate mercurial/sshserver.py @ 30001:e38d85be978f
repair: open a file with checkambig=True to avoid file stat ambiguity
Before this patch, if steps below occurs at "the same time in sec",
all of mtime, ctime and size are same between (1) and (3).
1. append data to revlog-style file (and close transaction)
2. discard appended data by truncation of strip
3. append same size but different data to revlog-style file again
Therefore, cache validation doesn't work after (3) as expected.
To avoid such file stat ambiguity around truncation, this patch opens
a file with checkambig=True.
This patch also introduces "with" statement style, to ensure immediate
invocation of close() after truncation, because closing file is the
only trigger to check (and get rid of) file stat ambiguity.
This is a part of ExactCacheValidationPlan.
https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Thu, 22 Sep 2016 21:52:00 +0900 |
parents | 1a29db79a98d |
children | d34cf260d15b |
rev | line source |
---|---|
2399 | 1 # sshserver.py - ssh protocol server support for mercurial |
2396 | 2 # |
4635
63b9d2deed48
Updated copyright notices and add "and others" to "hg version"
Thomas Arendsen Hein <thomas@intevation.de>
parents:
4258
diff
changeset
|
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
2859 | 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
2396 | 5 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8109
diff
changeset
|
6 # This software may be used and distributed according to the terms of the |
10263 | 7 # GNU General Public License version 2 or any later version. |
2396 | 8 |
25976
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
9 from __future__ import absolute_import |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
10 |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
11 import os |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
12 import sys |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
13 |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
26587
diff
changeset
|
14 from .i18n import _ |
25976
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
15 from . import ( |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25976
diff
changeset
|
16 error, |
25976
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
17 hook, |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
18 util, |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
19 wireproto, |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
20 ) |
2396 | 21 |
20903
8d477543882b
wireproto: introduce an abstractserverproto class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
17563
diff
changeset
|
22 class sshserver(wireproto.abstractserverproto): |
2396 | 23 def __init__(self, ui, repo): |
24 self.ui = ui | |
25 self.repo = repo | |
26 self.lock = None | |
14614
afccc64eea73
ui: use I/O descriptors internally
Idan Kamara <idankk86@gmail.com>
parents:
14233
diff
changeset
|
27 self.fin = ui.fin |
afccc64eea73
ui: use I/O descriptors internally
Idan Kamara <idankk86@gmail.com>
parents:
14233
diff
changeset
|
28 self.fout = ui.fout |
2396 | 29 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4635
diff
changeset
|
30 hook.redirect(True) |
14614
afccc64eea73
ui: use I/O descriptors internally
Idan Kamara <idankk86@gmail.com>
parents:
14233
diff
changeset
|
31 ui.fout = repo.ui.fout = ui.ferr |
2396 | 32 |
33 # Prevent insertion/deletion of CRs | |
14233
659f34b833b9
rename util.set_binary to setbinary
Adrian Buehlmann <adrian@cadifra.com>
parents:
13721
diff
changeset
|
34 util.setbinary(self.fin) |
659f34b833b9
rename util.set_binary to setbinary
Adrian Buehlmann <adrian@cadifra.com>
parents:
13721
diff
changeset
|
35 util.setbinary(self.fout) |
2396 | 36 |
11579 | 37 def getargs(self, args): |
38 data = {} | |
39 keys = args.split() | |
40 for n in xrange(len(keys)): | |
41 argline = self.fin.readline()[:-1] | |
42 arg, l = argline.split() | |
43 if arg not in keys: | |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
26587
diff
changeset
|
44 raise error.Abort(_("unexpected parameter %r") % arg) |
11579 | 45 if arg == '*': |
46 star = {} | |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13719
diff
changeset
|
47 for k in xrange(int(l)): |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13719
diff
changeset
|
48 argline = self.fin.readline()[:-1] |
11579 | 49 arg, l = argline.split() |
50 val = self.fin.read(int(l)) | |
51 star[arg] = val | |
52 data['*'] = star | |
53 else: | |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13719
diff
changeset
|
54 val = self.fin.read(int(l)) |
11579 | 55 data[arg] = val |
56 return [data[k] for k in keys] | |
57 | |
58 def getarg(self, name): | |
59 return self.getargs(name)[0] | |
2396 | 60 |
11621
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
61 def getfile(self, fpout): |
11622
1d48681b17a4
protocol: rename send methods to get grouping by prefix
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11621
diff
changeset
|
62 self.sendresponse('') |
11621
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
63 count = int(self.fin.readline()) |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
64 while count: |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
65 fpout.write(self.fin.read(count)) |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
66 count = int(self.fin.readline()) |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
67 |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
68 def redirect(self): |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
69 pass |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
70 |
11623
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
71 def groupchunks(self, changegroup): |
29728
1a29db79a98d
sshserver: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents:
29389
diff
changeset
|
72 return iter(lambda: changegroup.read(4096), '') |
11584
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
73 |
11623
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
74 def sendresponse(self, v): |
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
75 self.fout.write("%d\n" % len(v)) |
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
76 self.fout.write(v) |
11584
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
77 self.fout.flush() |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
78 |
11585
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
79 def sendstream(self, source): |
17563
46db0ec640f3
sshserver: avoid a multi-dot attribute lookup in a hot loop
Bryan O'Sullivan <bryano@fb.com>
parents:
15585
diff
changeset
|
80 write = self.fout.write |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
81 for chunk in source.gen: |
17563
46db0ec640f3
sshserver: avoid a multi-dot attribute lookup in a hot loop
Bryan O'Sullivan <bryano@fb.com>
parents:
15585
diff
changeset
|
82 write(chunk) |
11585
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
83 self.fout.flush() |
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
84 |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
85 def sendpushresponse(self, rsp): |
11622
1d48681b17a4
protocol: rename send methods to get grouping by prefix
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11621
diff
changeset
|
86 self.sendresponse('') |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
87 self.sendresponse(str(rsp.res)) |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
88 |
12703
40bb5853fc4b
wireproto: introduce pusherr() to deal with "unsynced changes" error
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
12337
diff
changeset
|
89 def sendpusherror(self, rsp): |
40bb5853fc4b
wireproto: introduce pusherr() to deal with "unsynced changes" error
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
12337
diff
changeset
|
90 self.sendresponse(rsp.res) |
40bb5853fc4b
wireproto: introduce pusherr() to deal with "unsynced changes" error
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
12337
diff
changeset
|
91 |
15017
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
92 def sendooberror(self, rsp): |
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
93 self.ui.ferr.write('%s\n-\n' % rsp.message) |
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
94 self.ui.ferr.flush() |
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
95 self.fout.write('\n') |
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
96 self.fout.flush() |
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
97 |
2396 | 98 def serve_forever(self): |
8109
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
99 try: |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
100 while self.serve_one(): |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
101 pass |
8109
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
102 finally: |
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
103 if self.lock is not None: |
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
104 self.lock.release() |
2396 | 105 sys.exit(0) |
106 | |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
107 handlers = { |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
108 str: sendresponse, |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
109 wireproto.streamres: sendstream, |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
110 wireproto.pushres: sendpushresponse, |
12703
40bb5853fc4b
wireproto: introduce pusherr() to deal with "unsynced changes" error
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
12337
diff
changeset
|
111 wireproto.pusherr: sendpusherror, |
15017
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14614
diff
changeset
|
112 wireproto.ooberror: sendooberror, |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
113 } |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
114 |
2396 | 115 def serve_one(self): |
116 cmd = self.fin.readline()[:-1] | |
11618
83070a9cd526
protocol: command must be checked before passing in
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11596
diff
changeset
|
117 if cmd and cmd in wireproto.commands: |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
118 rsp = wireproto.dispatch(self.repo, self, cmd) |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
119 self.handlers[rsp.__class__](self, rsp) |
11618
83070a9cd526
protocol: command must be checked before passing in
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11596
diff
changeset
|
120 elif cmd: |
2396 | 121 impl = getattr(self, 'do_' + cmd, None) |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
122 if impl: |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
123 r = impl() |
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
124 if r is not None: |
11622
1d48681b17a4
protocol: rename send methods to get grouping by prefix
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11621
diff
changeset
|
125 self.sendresponse(r) |
1d48681b17a4
protocol: rename send methods to get grouping by prefix
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11621
diff
changeset
|
126 else: self.sendresponse("") |
2396 | 127 return cmd != '' |
128 | |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
129 def _client(self): |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2622
diff
changeset
|
130 client = os.environ.get('SSH_CLIENT', '').split(' ', 1)[0] |
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2622
diff
changeset
|
131 return 'remote:ssh:' + client |