##// END OF EJS Templates
make static-http work with empty repos (issue965)
Dirkjan Ochtman -
r6028:6605a03c default
parent child Browse files
Show More
@@ -1,78 +1,86 b''
1 # statichttprepo.py - simple http repository class for mercurial
1 # statichttprepo.py - simple http repository class for mercurial
2 #
2 #
3 # This provides read-only repo access to repositories exported via static http
3 # This provides read-only repo access to repositories exported via static http
4 #
4 #
5 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
5 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
6 #
6 #
7 # This software may be used and distributed according to the terms
7 # This software may be used and distributed according to the terms
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 from i18n import _
10 from i18n import _
11 import changelog, filelog, httprangereader
11 import changelog, filelog, httprangereader
12 import repo, localrepo, manifest, os, urllib, urllib2, util
12 import repo, localrepo, manifest, util
13 import urllib, urllib2, errno
13
14
14 class rangereader(httprangereader.httprangereader):
15 class rangereader(httprangereader.httprangereader):
15 def read(self, size=None):
16 def read(self, size=None):
16 try:
17 try:
17 return httprangereader.httprangereader.read(self, size)
18 return httprangereader.httprangereader.read(self, size)
18 except urllib2.HTTPError, inst:
19 except urllib2.HTTPError, inst:
19 raise IOError(None, inst)
20 num = inst.code == 404 and errno.ENOENT or None
21 raise IOError(num, inst)
20 except urllib2.URLError, inst:
22 except urllib2.URLError, inst:
21 raise IOError(None, inst.reason[1])
23 raise IOError(None, inst.reason[1])
22
24
23 def opener(base):
25 def opener(base):
24 """return a function that opens files over http"""
26 """return a function that opens files over http"""
25 p = base
27 p = base
26 def o(path, mode="r"):
28 def o(path, mode="r"):
27 f = "/".join((p, urllib.quote(path)))
29 f = "/".join((p, urllib.quote(path)))
28 return rangereader(f)
30 return rangereader(f)
29 return o
31 return o
30
32
31 class statichttprepository(localrepo.localrepository):
33 class statichttprepository(localrepo.localrepository):
32 def __init__(self, ui, path):
34 def __init__(self, ui, path):
33 self._url = path
35 self._url = path
34 self.ui = ui
36 self.ui = ui
35
37
36 self.path = path.rstrip('/') + "/.hg"
38 self.path = path.rstrip('/') + "/.hg"
37 self.opener = opener(self.path)
39 self.opener = opener(self.path)
40
38 # find requirements
41 # find requirements
39 try:
42 try:
40 requirements = self.opener("requires").read().splitlines()
43 requirements = self.opener("requires").read().splitlines()
41 except IOError:
44 except IOError, inst:
42 requirements = []
45 if inst.errno == errno.ENOENT:
46 msg = _("'%s' does not appear to be an hg repository") % path
47 raise repo.RepoError(msg)
48 else:
49 requirements = []
50
43 # check them
51 # check them
44 for r in requirements:
52 for r in requirements:
45 if r not in self.supported:
53 if r not in self.supported:
46 raise repo.RepoError(_("requirement '%s' not supported") % r)
54 raise repo.RepoError(_("requirement '%s' not supported") % r)
47
55
48 # setup store
56 # setup store
49 if "store" in requirements:
57 if "store" in requirements:
50 self.encodefn = util.encodefilename
58 self.encodefn = util.encodefilename
51 self.decodefn = util.decodefilename
59 self.decodefn = util.decodefilename
52 self.spath = self.path + "/store"
60 self.spath = self.path + "/store"
53 else:
61 else:
54 self.encodefn = lambda x: x
62 self.encodefn = lambda x: x
55 self.decodefn = lambda x: x
63 self.decodefn = lambda x: x
56 self.spath = self.path
64 self.spath = self.path
57 self.sopener = util.encodedopener(opener(self.spath), self.encodefn)
65 self.sopener = util.encodedopener(opener(self.spath), self.encodefn)
58
66
59 self.manifest = manifest.manifest(self.sopener)
67 self.manifest = manifest.manifest(self.sopener)
60 self.changelog = changelog.changelog(self.sopener)
68 self.changelog = changelog.changelog(self.sopener)
61 self.tagscache = None
69 self.tagscache = None
62 self.nodetagscache = None
70 self.nodetagscache = None
63 self.encodepats = None
71 self.encodepats = None
64 self.decodepats = None
72 self.decodepats = None
65
73
66 def url(self):
74 def url(self):
67 return 'static-' + self._url
75 return 'static-' + self._url
68
76
69 def dev(self):
77 def dev(self):
70 return -1
78 return -1
71
79
72 def local(self):
80 def local(self):
73 return False
81 return False
74
82
75 def instance(ui, path, create):
83 def instance(ui, path, create):
76 if create:
84 if create:
77 raise util.Abort(_('cannot create new static-http repository'))
85 raise util.Abort(_('cannot create new static-http repository'))
78 return statichttprepository(ui, path[7:])
86 return statichttprepository(ui, path[7:])
@@ -1,66 +1,81 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cp "$TESTDIR"/printenv.py .
3 cp "$TESTDIR"/printenv.py .
4
4
5 http_proxy= hg clone static-http://localhost:$HGPORT/ copy
5 http_proxy= hg clone static-http://localhost:$HGPORT/ copy
6 echo $?
6 echo $?
7 test -d copy || echo copy: No such file or directory
7 test -d copy || echo copy: No such file or directory
8
8
9 # This server doesn't do range requests so it's basically only good for
9 # This server doesn't do range requests so it's basically only good for
10 # one pull
10 # one pull
11 cat > dumb.py <<EOF
11 cat > dumb.py <<EOF
12 import BaseHTTPServer, SimpleHTTPServer, os, signal
12 import BaseHTTPServer, SimpleHTTPServer, os, signal
13
13
14 def run(server_class=BaseHTTPServer.HTTPServer,
14 def run(server_class=BaseHTTPServer.HTTPServer,
15 handler_class=SimpleHTTPServer.SimpleHTTPRequestHandler):
15 handler_class=SimpleHTTPServer.SimpleHTTPRequestHandler):
16 server_address = ('localhost', int(os.environ['HGPORT']))
16 server_address = ('localhost', int(os.environ['HGPORT']))
17 httpd = server_class(server_address, handler_class)
17 httpd = server_class(server_address, handler_class)
18 httpd.serve_forever()
18 httpd.serve_forever()
19
19
20 signal.signal(signal.SIGTERM, lambda x: sys.exit(0))
20 signal.signal(signal.SIGTERM, lambda x: sys.exit(0))
21 run()
21 run()
22 EOF
22 EOF
23
23
24 python dumb.py 2>/dev/null &
24 python dumb.py 2>/dev/null &
25 echo $! >> $DAEMON_PIDS
25 echo $! >> $DAEMON_PIDS
26
26
27 mkdir remote
27 mkdir remote
28 cd remote
28 cd remote
29 hg init
29 hg init
30 echo foo > bar
30 echo foo > bar
31 hg add bar
31 hg add bar
32 hg commit -m"test" -d "1000000 0"
32 hg commit -m"test" -d "1000000 0"
33 hg tip
33 hg tip
34
34
35 cd ..
35 cd ..
36
36
37 http_proxy= hg clone static-http://localhost:$HGPORT/remote local | sed -e 's,:[0-9][0-9]*/,/,'
37 http_proxy= hg clone static-http://localhost:$HGPORT/remote local | sed -e 's,:[0-9][0-9]*/,/,'
38
38
39 cd local
39 cd local
40 hg verify
40 hg verify
41 cat bar
41 cat bar
42
42
43 cd ../remote
43 cd ../remote
44 echo baz > quux
44 echo baz > quux
45 hg commit -A -mtest2 -d '100000000 0'
45 hg commit -A -mtest2 -d '100000000 0'
46
46
47 cd ../local
47 cd ../local
48 echo '[hooks]' >> .hg/hgrc
48 echo '[hooks]' >> .hg/hgrc
49 echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc
49 echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc
50 http_proxy= hg pull | sed -e 's,:[0-9][0-9]*/,/,'
50 http_proxy= hg pull | sed -e 's,:[0-9][0-9]*/,/,'
51
51
52 echo '% test with "/" URI (issue 747)'
52 echo '% test with "/" URI (issue 747)'
53 cd ..
53 cd ..
54 hg init
54 hg init
55 echo a > a
55 echo a > a
56 hg add a
56 hg add a
57 hg ci -ma
57 hg ci -ma
58
58
59 http_proxy= hg clone static-http://localhost:$HGPORT/ local2 | sed -e 's,:[0-9][0-9]*/,/,'
59 http_proxy= hg clone static-http://localhost:$HGPORT/ local2 | sed -e 's,:[0-9][0-9]*/,/,'
60
60
61 cd local2
61 cd local2
62 hg verify
62 hg verify
63 cat a
63 cat a
64 hg paths | sed -e 's,:[0-9][0-9]*/,/,'
64 hg paths | sed -e 's,:[0-9][0-9]*/,/,'
65
65
66 echo '% test with empty repo (issue965)'
67 cd ..
68 hg init remotempty
69
70 http_proxy= hg clone static-http://localhost:$HGPORT/remotempty local3 | sed -e 's,:[0-9][0-9]*/,/,'
71
72 cd local3
73 hg verify
74 hg paths | sed -e 's,:[0-9][0-9]*/,/,'
75
76 echo '% test with non-repo'
77 cd ..
78 mkdir notarepo
79 http_proxy= hg clone static-http://localhost:$HGPORT/notarepo local3 2>&1 | sed -e 's,:[0-9][0-9]*/,/,'
80
66 kill $!
81 kill $!
@@ -1,44 +1,55 b''
1 abort: Connection refused
1 abort: Connection refused
2 255
2 255
3 copy: No such file or directory
3 copy: No such file or directory
4 changeset: 0:53e17d176ae6
4 changeset: 0:53e17d176ae6
5 tag: tip
5 tag: tip
6 user: test
6 user: test
7 date: Mon Jan 12 13:46:40 1970 +0000
7 date: Mon Jan 12 13:46:40 1970 +0000
8 summary: test
8 summary: test
9
9
10 requesting all changes
10 requesting all changes
11 adding changesets
11 adding changesets
12 adding manifests
12 adding manifests
13 adding file changes
13 adding file changes
14 added 1 changesets with 1 changes to 1 files
14 added 1 changesets with 1 changes to 1 files
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 checking changesets
16 checking changesets
17 checking manifests
17 checking manifests
18 crosschecking files in changesets and manifests
18 crosschecking files in changesets and manifests
19 checking files
19 checking files
20 1 files, 1 changesets, 1 total revisions
20 1 files, 1 changesets, 1 total revisions
21 foo
21 foo
22 adding quux
22 adding quux
23 changegroup hook: HG_NODE=34401e0e9971e9720b613d9089ffa9a6eefb3d2d HG_SOURCE=pull HG_URL=static-http://localhost/remote
23 changegroup hook: HG_NODE=34401e0e9971e9720b613d9089ffa9a6eefb3d2d HG_SOURCE=pull HG_URL=static-http://localhost/remote
24 pulling from static-http://localhost/remote
24 pulling from static-http://localhost/remote
25 searching for changes
25 searching for changes
26 adding changesets
26 adding changesets
27 adding manifests
27 adding manifests
28 adding file changes
28 adding file changes
29 added 1 changesets with 1 changes to 1 files
29 added 1 changesets with 1 changes to 1 files
30 (run 'hg update' to get a working copy)
30 (run 'hg update' to get a working copy)
31 % test with "/" URI (issue 747)
31 % test with "/" URI (issue 747)
32 requesting all changes
32 requesting all changes
33 adding changesets
33 adding changesets
34 adding manifests
34 adding manifests
35 adding file changes
35 adding file changes
36 added 1 changesets with 1 changes to 1 files
36 added 1 changesets with 1 changes to 1 files
37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 checking changesets
38 checking changesets
39 checking manifests
39 checking manifests
40 crosschecking files in changesets and manifests
40 crosschecking files in changesets and manifests
41 checking files
41 checking files
42 1 files, 1 changesets, 1 total revisions
42 1 files, 1 changesets, 1 total revisions
43 a
43 a
44 default = static-http://localhost/
44 default = static-http://localhost/
45 % test with empty repo (issue965)
46 no changes found
47 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 checking changesets
49 checking manifests
50 crosschecking files in changesets and manifests
51 checking files
52 0 files, 0 changesets, 0 total revisions
53 default = static-http://localhost/remotempty
54 % test with non-repo
55 abort: 'http://localhost/notarepo' does not appear to be an hg repository!
General Comments 0
You need to be logged in to leave comments. Login now