changeset 232:0ba1aee0467c

initial support for pull -r
author Abderrahim Kitouni <a.kitouni@gmail.com>
date Sat, 01 Aug 2009 17:55:54 +0100
parents bdaec2a079ce
children 57f860801ab0
files git_handler.py gitrepo.py hgrepo.py tests/test-pull tests/test-pull.out
diffstat 5 files changed, 149 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/git_handler.py
+++ b/git_handler.py
@@ -97,9 +97,9 @@
         self.import_git_objects(remote_name)
         self.save_map()
 
-    def fetch(self, remote):
+    def fetch(self, remote, heads):
         self.export_git_objects()
-        refs = self.fetch_pack(remote)
+        refs = self.fetch_pack(remote, heads)
         remote_name = self.remote_name(remote)
 
         if refs:
@@ -344,7 +344,10 @@
         # get a list of all the head shas
         if refs:
           for head, sha in refs.iteritems():
-              todo.append(sha)
+              # refs contains all the refs in the server, not just the ones
+              # we are pulling
+              if sha in self.git.object_store:
+                  todo.append(sha)
         else:
             todo = self.git.refs.values()[:]
 
@@ -551,10 +554,24 @@
         return new_refs
 
 
-    def fetch_pack(self, remote_name):
+    def fetch_pack(self, remote_name, heads):
         client, path = self.get_transport_and_path(remote_name)
         graphwalker = self.git.get_graph_walker()
-        determine_wants = self.git.object_store.determine_wants_all
+        def determine_wants(refs):
+            if heads:
+                want = []
+                for h in heads:
+                    r = [ref for ref in refs if ref.endswith('/'+h)]
+                    if not r:
+                        raise hgutil.Abort("ref %s not found on remote server")
+                    elif len(r) == 1:
+                        want.append(refs[r[0]])
+                    else:
+                        raise hgutil.Abort("ambiguous reference %s: %r"%(h, r))
+            else:
+                want = [sha for ref, sha in refs.iteritems()
+                        if not ref.endswith('^{}')]
+            return want
         f, commit = self.git.object_store.add_pack()
         try:
             return client.fetch_pack(path, determine_wants, graphwalker, f.write, self.ui.status)
@@ -595,6 +612,10 @@
             parts = k.split('/')
             if parts[0] == 'refs' and parts[1] == 'tags':
                 ref_name = "/".join([v for v in parts[2:]])
+                # refs contains all the refs in the server, not just
+                # the ones we are pulling
+                if refs[k] not in self.git.object_store:
+                    continue
                 if ref_name[-3:] == '^{}':
                     ref_name = ref_name[:-3]
                 if not ref_name in self.repo.tags():
@@ -619,6 +640,10 @@
                           if ref.startswith('refs/heads/')])
 
             for head, sha in heads.iteritems():
+                # refs contains all the refs in the server, not just
+                # the ones we are pulling
+                if sha not in self.git.object_store:
+                    continue
                 hgsha = bin(self.map_hg_get(sha))
                 if not head in bms:
                     # new branch
@@ -640,6 +665,10 @@
                       if ref.startswith('refs/heads/')])
 
         for head, sha in heads.iteritems():
+            # refs contains all the refs in the server, not just the ones
+            # we are pulling
+            if sha not in self.git.object_store:
+                continue
             hgsha = bin(self.map_hg_get(sha))
             tag = '%s/%s' % (remote_name, head)
             self.repo.tag(tag, hgsha, '', True, None, None)
--- a/gitrepo.py
+++ b/gitrepo.py
@@ -2,10 +2,13 @@
 from git_handler import GitHandler
 
 class gitrepo(repo.repository):
-    capabilities = []
+    capabilities = ['lookup']
     def __init__(self, ui, path, create):
         if create: # pragma: no cover
             raise util.Abort('Cannot create a git repository.')
         self.path = path
+    def lookup(self, key):
+        if isinstance(key, str):
+            return key
 
 instance = gitrepo
--- a/hgrepo.py
+++ b/hgrepo.py
@@ -13,7 +13,7 @@
         def pull(self, remote, heads=None, force=False):
             if isinstance(remote, gitrepo):
                 git = GitHandler(self, self.ui)
-                git.fetch(remote.path)
+                git.fetch(remote.path, heads)
             else: #pragma: no cover
                 return super(hgrepo, self).pull(remote, heads, force)
 
new file mode 100755
--- /dev/null
+++ b/tests/test-pull
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+# Fails for some reason, need to investigate
+# "$TESTDIR/hghave" git || exit 80
+
+# bail early if the user is already running git-daemon
+echo hi | nc localhost 9418 2>/dev/null && exit 80
+
+echo "[extensions]" >> $HGRCPATH
+echo "hggit=$(echo $(dirname $(dirname $0)))" >> $HGRCPATH
+echo 'hgext.graphlog =' >> $HGRCPATH
+echo 'hgext.bookmarks =' >> $HGRCPATH
+
+GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
+GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
+GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
+GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
+GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
+GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
+
+count=10
+commit()
+{
+    GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
+    GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
+    git commit "$@" >/dev/null 2>/dev/null || echo "git commit error"
+    count=`expr $count + 1`
+}
+
+mkdir gitrepo
+cd gitrepo
+git init | python -c "import sys; print sys.stdin.read().replace('$(dirname $(pwd))/', '')"
+echo alpha > alpha
+git add alpha
+commit -m 'add alpha'
+
+git tag alpha
+
+git checkout -b beta
+echo beta > beta
+git add beta
+commit -m 'add beta'
+
+
+cd ..
+git daemon --base-path="$(pwd)"\
+ --listen=localhost\
+ --export-all\
+ --pid-file=gitdaemon.pid \
+ --detach --reuseaddr
+
+echo % clone a tag
+hg clone -r alpha git://localhost/gitrepo hgrepo-a
+cd hgrepo-a
+hg log --graph
+
+cd ..
+echo % clone a branch
+hg clone -r beta git://localhost/gitrepo hgrepo-b
+cd hgrepo-b
+hg log --graph
+
+
+cd ..
+kill `cat gitdaemon.pid`
new file mode 100644
--- /dev/null
+++ b/tests/test-pull.out
@@ -0,0 +1,45 @@
+Initialized empty Git repository in gitrepo/.git/
+
+Switched to a new branch "beta"
+% clone a tag
+importing Hg objects into Git
+Counting objects: 3, done.
+Total 3 (delta 0), reused 0 (delta 0)
+importing Git objects into Hg
+at: 0/1
+updating working directory
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+@  changeset:   0:3442585be8a6
+   tag:         alpha
+   tag:         default/master
+   tag:         tip
+   tag:         master
+   user:        test <test@example.org>
+   date:        Mon Jan 01 00:00:10 2007 +0000
+   summary:     add alpha
+
+% clone a branch
+importing Hg objects into Git
+Counting objects: 6, done.
+Compressing objects:  33% (1/3)   
Compressing objects:  66% (2/3)   
Compressing objects: 100% (3/3)   
Compressing objects: 100% (3/3), done.
+Total 6 (delta 0), reused 0 (delta 0)
+importing Git objects into Hg
+at: 0/2
+updating working directory
+2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+@  changeset:   1:7bcd915dc873
+|  tag:         default/beta
+|  tag:         beta
+|  tag:         tip
+|  user:        test <test@example.org>
+|  date:        Mon Jan 01 00:00:11 2007 +0000
+|  summary:     add beta
+|
+o  changeset:   0:3442585be8a6
+   tag:         master
+   tag:         alpha
+   tag:         default/master
+   user:        test <test@example.org>
+   date:        Mon Jan 01 00:00:10 2007 +0000
+   summary:     add alpha
+