Mercurial > hg
annotate mercurial/sshserver.py @ 34682:7e3001b74ab3
tersestatus: re-implement the functionality to terse the status
The previous terse status implementation was hacking around os.listdir() and was
flaky. There have been a lot of instances of mercurial buildbots failing
and google's internal builds failing because of the
hacky implementation of terse status. Even though I wrote the last
implementation but it was hard for me to find the reason for the flake.
The new implementation can be slower than the old one but is clean and easy to
understand.
In this we create a node object for each directory and create a tree
like structure starting from the root of the working copy. While building the
tree like structure we store some information on the nodes which will be helpful
for deciding later whether we can terse the dir or not.
Once the whole tree is build we traverse and built the list of files for each
status with required tersing.
There is no behaviour change as the old test, test-status-terse.t passes with
the new implementation.
Differential Revision: https://phab.mercurial-scm.org/D985
author | Pulkit Goyal <7895pulkit@gmail.com> |
---|---|
date | Fri, 06 Oct 2017 20:54:23 +0530 |
parents | 5326e4ef1dab |
children | 8cdb671dbd0b |
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 sys |
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
12 |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
26587
diff
changeset
|
13 from .i18n import _ |
25976
72b36785d7f4
sshserver: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25692
diff
changeset
|
14 from . import ( |
30635
a150173da1c1
py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30562
diff
changeset
|
15 encoding, |
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 |
30562
b3a9ef3d30e8
protocol: declare transport protocol name
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30466
diff
changeset
|
29 self.name = 'ssh' |
2396 | 30 |
5833
323b9c55b328
hook: redirect stdout to stderr for ssh and http servers
Matt Mackall <mpm@selenic.com>
parents:
4635
diff
changeset
|
31 hook.redirect(True) |
14614
afccc64eea73
ui: use I/O descriptors internally
Idan Kamara <idankk86@gmail.com>
parents:
14233
diff
changeset
|
32 ui.fout = repo.ui.fout = ui.ferr |
2396 | 33 |
34 # Prevent insertion/deletion of CRs | |
14233
659f34b833b9
rename util.set_binary to setbinary
Adrian Buehlmann <adrian@cadifra.com>
parents:
13721
diff
changeset
|
35 util.setbinary(self.fin) |
659f34b833b9
rename util.set_binary to setbinary
Adrian Buehlmann <adrian@cadifra.com>
parents:
13721
diff
changeset
|
36 util.setbinary(self.fout) |
2396 | 37 |
11579 | 38 def getargs(self, args): |
39 data = {} | |
40 keys = args.split() | |
41 for n in xrange(len(keys)): | |
42 argline = self.fin.readline()[:-1] | |
43 arg, l = argline.split() | |
44 if arg not in keys: | |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
26587
diff
changeset
|
45 raise error.Abort(_("unexpected parameter %r") % arg) |
11579 | 46 if arg == '*': |
47 star = {} | |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13719
diff
changeset
|
48 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
|
49 argline = self.fin.readline()[:-1] |
11579 | 50 arg, l = argline.split() |
51 val = self.fin.read(int(l)) | |
52 star[arg] = val | |
53 data['*'] = star | |
54 else: | |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13719
diff
changeset
|
55 val = self.fin.read(int(l)) |
11579 | 56 data[arg] = val |
57 return [data[k] for k in keys] | |
58 | |
59 def getarg(self, name): | |
60 return self.getargs(name)[0] | |
2396 | 61 |
11621
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
62 def getfile(self, fpout): |
11622
1d48681b17a4
protocol: rename send methods to get grouping by prefix
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11621
diff
changeset
|
63 self.sendresponse('') |
11621
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
64 count = int(self.fin.readline()) |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
65 while count: |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
66 fpout.write(self.fin.read(count)) |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
67 count = int(self.fin.readline()) |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
68 |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
69 def redirect(self): |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
70 pass |
e46a8b2331a6
protocol: shuffle server methods to group send methods
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11618
diff
changeset
|
71 |
11623
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
72 def sendresponse(self, v): |
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
73 self.fout.write("%d\n" % len(v)) |
31d0a6d50ee2
protocol: extract compression from streaming mechanics
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11622
diff
changeset
|
74 self.fout.write(v) |
11584
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
75 self.fout.flush() |
1af96b090116
protocol: unify changegroup commands
Matt Mackall <mpm@selenic.com>
parents:
11581
diff
changeset
|
76 |
11585
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
77 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
|
78 write = self.fout.write |
30466
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
79 |
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
80 if source.reader: |
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
81 gen = iter(lambda: source.reader.read(4096), '') |
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
82 else: |
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
83 gen = source.gen |
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
84 |
2add671bf55b
wireproto: perform chunking and compression at protocol layer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
30206
diff
changeset
|
85 for chunk in gen: |
17563
46db0ec640f3
sshserver: avoid a multi-dot attribute lookup in a hot loop
Bryan O'Sullivan <bryano@fb.com>
parents:
15585
diff
changeset
|
86 write(chunk) |
11585
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
87 self.fout.flush() |
5d907fbb9703
protocol: unify stream_out command
Matt Mackall <mpm@selenic.com>
parents:
11584
diff
changeset
|
88 |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
89 def sendpushresponse(self, rsp): |
11622
1d48681b17a4
protocol: rename send methods to get grouping by prefix
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11621
diff
changeset
|
90 self.sendresponse('') |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
91 self.sendresponse(str(rsp.res)) |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
92 |
12703
40bb5853fc4b
wireproto: introduce pusherr() to deal with "unsynced changes" error
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
12337
diff
changeset
|
93 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
|
94 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
|
95 |
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
|
96 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
|
97 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
|
98 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
|
99 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
|
100 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
|
101 |
2396 | 102 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
|
103 try: |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
104 while self.serve_one(): |
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
105 pass |
8109
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
106 finally: |
496ae1ea4698
switch lock releasing in the core from gc to explicit
Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>
parents:
7875
diff
changeset
|
107 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
|
108 self.lock.release() |
2396 | 109 sys.exit(0) |
110 | |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
111 handlers = { |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
112 str: sendresponse, |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
113 wireproto.streamres: sendstream, |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
114 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
|
115 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
|
116 wireproto.ooberror: sendooberror, |
11625
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
117 } |
cdeb861335d5
protocol: wrap non-string protocol responses in classes
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11623
diff
changeset
|
118 |
2396 | 119 def serve_one(self): |
120 cmd = self.fin.readline()[:-1] | |
11618
83070a9cd526
protocol: command must be checked before passing in
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
11596
diff
changeset
|
121 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
|
122 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
|
123 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
|
124 elif cmd: |
2396 | 125 impl = getattr(self, 'do_' + cmd, None) |
10282
08a0f04b56bd
many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents:
10263
diff
changeset
|
126 if impl: |
11580
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
127 r = impl() |
69248b5add46
protocol: move most ssh responses to returns
Matt Mackall <mpm@selenic.com>
parents:
11579
diff
changeset
|
128 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
|
129 self.sendresponse(r) |
34435
5326e4ef1dab
style: never put multiple statements on one line
Alex Gaynor <agaynor@mozilla.com>
parents:
30635
diff
changeset
|
130 else: |
5326e4ef1dab
style: never put multiple statements on one line
Alex Gaynor <agaynor@mozilla.com>
parents:
30635
diff
changeset
|
131 self.sendresponse("") |
2396 | 132 return cmd != '' |
133 | |
11593
d054cc5c7737
protocol: unify unbundle on the server side
Matt Mackall <mpm@selenic.com>
parents:
11585
diff
changeset
|
134 def _client(self): |
30635
a150173da1c1
py3: replace os.environ with encoding.environ (part 2 of 5)
Pulkit Goyal <7895pulkit@gmail.com>
parents:
30562
diff
changeset
|
135 client = encoding.environ.get('SSH_CLIENT', '').split(' ', 1)[0] |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2622
diff
changeset
|
136 return 'remote:ssh:' + client |