[PATCH 1 of 2 bfiles] Support pushing to HTTP stores

alexandru alex at hackd.net
Thu Jun 3 17:47:05 CDT 2010


 bfiles.py |  73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 66 insertions(+), 7 deletions(-)


# HG changeset patch
# User alexandru <alex at hackd.net>
# Date 1275598699 25200
# Node ID 2bfadd624bb7ed9c29350ee9e5a791c3bbea222d
# Parent  947a5f96edcebdf693929788d1b13852b288b522
Support pushing to HTTP stores

diff -r 947a5f96edce -r 2bfadd624bb7 bfiles.py
--- a/bfiles.py	Wed Jun 02 19:07:19 2010 -0400
+++ b/bfiles.py	Thu Jun 03 13:58:19 2010 -0700
@@ -32,6 +32,7 @@
 import urlparse
 import urllib
 import urllib2
+import httplib
 import copy
 import inspect
 import fnmatch
@@ -1598,18 +1599,35 @@
 
 
 class httpstore(basestore):
+    """A store accessed via HTTP"""
     def __init__(self, ui, repo, url):
-        self.ui = ui
-        self.repo = repo
-        self.url = url
-        (baseurl, authinfo) = url_.getauthinfo(self.url)
+        super(httpstore, self).__init__(ui, repo, url)
+        self.rawurl, self.path = urlparse.urlsplit(self.url)[1:3]
+        baseurl, authinfo = url_.getauthinfo(self.url)
         self.opener = url_.opener(self.ui, authinfo)
 
     def put(self, source, filename, hash):
-        raise NotImplementedError('sorry, HTTP PUT not implemented yet')
+        destdir = os.path.join(self.path, filename)
+        dest = os.path.join(destdir, hash)
+        self.sendfile(source, dest)
+        self.ui.debug('put %s to remote store\n' % source)
 
-    def _verifyfile(self, cctx, cset, contents, standin, verified):
-        raise NotImplementedError('sorry, verify via HTTP not implemented yet')
+    def sendfile(self, filename, destname):
+        self.ui.debug('httpstore.sendfile(%s, %s)\n' % (filename, destname))
+        try:
+            fd = open(filename)
+            httpo = httplib.HTTPConnection(self.rawurl)
+            httpo.request('PUT', destname, fd)
+            resp = httpo.getresponse()
+            if resp.status != httplib.CREATED:
+                raise util.Abort(_('unable to PUT: %s\n') % resp.reason)
+            else:
+                self.ui.note(_('[OK] %s/%s\n') % (self.rawurl, resp.getheader('Location')))
+        except Exception, e:
+            raise util.Abort(_('%s') % e)
+        finally:
+            httpo.close()
+            fd.close()
 
     def _getfile(self, tmpfile, filename, hash):
         (baseurl, authinfo) = url_.getauthinfo(self.url)
@@ -1628,6 +1646,47 @@
             raise util.Abort('%s: %s' % (baseurl, reason))
         return _copy_and_hash(_blockstream(infile), tmpfile)
 
+    def _verifyfile(self, cctx, cset, contents, standin, verified):
+        filename = _split_standin(standin)
+        if not filename:
+            return False
+        fctx = cctx[standin]
+        key = (filename, fctx.filenode())
+        if key in verified:
+            return False
+
+        expect_hash = fctx.data()[0:40]
+        store_path = os.path.join(self.path, filename, expect_hash)
+        verified.add(key)
+
+        try:
+            httpo = httplib.HTTPConnection(self.rawurl)
+            httpo.request('HEAD', store_path)
+            resp = httpo.getresponse()
+            if resp.status == httplib.NOT_FOUND:
+                self.ui.warn(
+                    _('changeset %s: %s missing\n (%s)\n')
+                    % (cset, filename, store_path))
+                return True                 # failed
+            elif resp.status == httplib.OK:
+                if contents:
+                    rhash = resp.getheader('Content-SHA1')
+                    if rhash != None and rhash == expect_hash:
+                        return False
+                    elif rhash == None:
+                        self.ui.warn(_('remote did not send a hash, '
+                        'it probably does not understand this protocol\n'))
+                        return False
+                    else:
+                        self.ui.warn(
+                            _('changeset %s: %s: contents differ\n (%s)\n')
+                            % (cset, filename, store_path))
+                        return True             # failed
+                return False
+            else:
+                raise util.Abort(_('check failed, unexpected response status: %d: %s') % (resp.status, resp.msg))
+        finally:
+            httpo.close()
 
 _store_klass = {
     'file':  localstore,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PGP.sig
Type: application/pgp-signature
Size: 314 bytes
Desc: not available
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20100603/42a212b4/attachment.pgp>


More information about the Mercurial-devel mailing list