Mercurial > hg-git
changeset 132:8cabda8ae1c6
merge from beejahth
author | Scott Chacon <schacon@gmail.com> |
---|---|
date | Tue, 19 May 2009 09:40:54 -0700 |
parents | 695a90e72e4f (diff) dd6c77ec206c (current diff) |
children | 2fa3ac775983 |
files | git_handler.py |
diffstat | 8 files changed, 203 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/dulwich/object_store.py Thu May 14 20:25:48 2009 -0700 +++ b/dulwich/object_store.py Tue May 19 09:40:54 2009 -0700 @@ -22,6 +22,7 @@ import itertools import os +import shutil import stat import tempfile import urllib2 @@ -248,7 +249,12 @@ basename = os.path.join(self.pack_dir, "pack-%s" % iter_sha1(entry[0] for entry in entries)) write_pack_index_v2(basename+".idx", entries, p.get_stored_checksum()) - os.rename(path, basename + ".pack") + try: + os.rename(path, basename + ".pack") + except OSError: + # Hack for Windows access denied error. + # TODO: mark the original for deletion later. + shutil.copyfile(path, basename + ".pack") self._add_known_pack(basename) def add_thin_pack(self):
--- a/dulwich/pack.py Thu May 14 20:25:48 2009 -0700 +++ b/dulwich/pack.py Tue May 19 09:40:54 2009 -0700 @@ -128,7 +128,7 @@ def load_pack_index(filename): - f = open(filename, 'r') + f = open(filename, 'rb') if f.read(4) == '\377tOc': version = struct.unpack(">L", f.read(4))[0] if version == 2: @@ -181,7 +181,7 @@ # ensure that it hasn't changed. self._size = os.path.getsize(filename) if file is None: - self._file = open(filename, 'r') + self._file = open(filename, 'rb') else: self._file = file self._contents, map_offset = simple_mmap(self._file, 0, self._size) @@ -733,7 +733,7 @@ :param objects: Iterable over (object, path) tuples to write :param num_objects: Number of objects to write """ - f = open(filename + ".pack", 'w') + f = open(filename + ".pack", 'wb') try: entries, data_sum = write_pack_data(f, objects, num_objects) finally: @@ -797,7 +797,7 @@ crc32_checksum. :param pack_checksum: Checksum of the pack file. """ - f = open(filename, 'w') + f = open(filename, 'wb') f = SHA1Writer(f) fan_out_table = defaultdict(lambda: 0) for (name, offset, entry_checksum) in entries: @@ -945,7 +945,7 @@ crc32_checksum. :param pack_checksum: Checksum of the pack file. """ - f = open(filename, 'w') + f = open(filename, 'wb') f = SHA1Writer(f) f.write('\377tOc') # Magic! f.write(struct.pack(">L", 2))
--- a/dulwich/repo.py Thu May 14 20:25:48 2009 -0700 +++ b/dulwich/repo.py Tue May 19 09:40:54 2009 -0700 @@ -173,14 +173,12 @@ def _get_ref(self, file): f = open(file, 'rb') try: - contents = f.read() + contents = f.read().strip() if contents.startswith(SYMREF): ref = contents[len(SYMREF):] - if ref[-1] == '\n': - ref = ref[:-1] return self.ref(ref) - assert len(contents) == 41, 'Invalid ref in %s' % file - return contents[:-1] + assert len(contents) == 40, 'Invalid ref in %s' % file + return contents finally: f.close() @@ -424,11 +422,10 @@ basefiles = set() changes = list() csha = None - ctree = None cmode = None if basetree: for (bmode, bname, bsha) in basetree.entries(): - if bmode == 57344: # TODO : properly handle submodules + if bmode == 0160000: # TODO : properly handle submodules continue basefiles.add(bname) bobj = self.get_object(bsha) @@ -438,6 +435,7 @@ if isinstance (bobj, Blob): changes.append (prefix + bname) elif isinstance(bobj, Tree): + ctree = None if csha: ctree = self.get_object(csha) changes.extend(filenames(bobj, @@ -447,7 +445,7 @@ # handle removals if comptree: for (bmode, bname, bsha, ) in comptree.entries(): - if bmode == 57344: # TODO: hande submodles + if bmode == 0160000: # TODO: hande submodles continue if bname not in basefiles: bobj = self.get_object(bsha)
--- a/git_handler.py Thu May 14 20:25:48 2009 -0700 +++ b/git_handler.py Tue May 19 09:40:54 2009 -0700 @@ -125,6 +125,7 @@ def push(self, remote_name): self.ui.status(_("pushing to : %s\n") % remote_name) self.export() + self.update_remote_references(remote_name) self.upload_pack(remote_name) def remote_add(self, remote_name, git_url): @@ -155,10 +156,36 @@ return self._config['remote.' + remote_name + '.url'] def update_references(self): - # TODO : if bookmarks exist, add them as git branches + try: + # We only care about bookmarks of the form 'name', + # not 'remote/name'. + def is_local_ref(item): return item[0].count('/') == 0 + bms = bookmarks.parse(self.repo) + bms = dict(filter(is_local_ref, bms.items())) + + # Create a local Git branch name for each + # Mercurial bookmark. + for key in bms: + hg_sha = hex(bms[key]) + git_sha = self.map_git_get(hg_sha) + self.git.set_ref('refs/heads/' + key, git_sha) + except AttributeError: + # No bookmarks extension + pass + c = self.map_git_get(hex(self.repo.changelog.tip())) self.git.set_ref('refs/heads/master', c) + # Make sure there's a refs/remotes/remote_name/name + # for every refs/heads/name + def update_remote_references(self, remote_name): + self.git.set_remote_refs(self.local_heads(), remote_name) + + def local_heads(self): + def is_local_head(item): return item[0].startswith('refs/heads') + refs = self.git.get_refs() + return dict(filter(is_local_head, refs.items())) + def export_git_objects(self): self.ui.status(_("exporting git objects\n")) total = len(self.repo.changelog) @@ -298,12 +325,17 @@ trees['/'] = [] trees['/'].append(fileentry) - # sort by tree depth, so we write the deepest trees first dirs = trees.keys() - dirs.sort(lambda a, b: len(b.split('/'))-len(a.split('/'))) - dirs.remove('/') - dirs.append('/') - + if dirs: + # sort by tree depth, so we write the deepest trees first + dirs.sort(lambda a, b: len(b.split('/'))-len(a.split('/'))) + dirs.remove('/') + dirs.append('/') + else: + # manifest is empty => make empty root tree + trees['/'] = [] + dirs = ['/'] + # write all the trees tree_sha = None tree_shas = {} @@ -369,6 +401,13 @@ if local_ref: if not local_ref == refs[ref_name]: changed[ref_name] = local_ref + + # Also push any local branches not on the server yet + for head in self.local_heads(): + if not head in refs: + ref = self.git.ref(head) + changed[head] = ref + return changed # takes a list of shas the server wants and shas the server has @@ -393,7 +432,7 @@ changes = list() changes.append((tree, path)) for (mode, name, sha) in tree.entries(): - if mode == 57344: # TODO : properly handle submodules and document what 57344 means + if mode == 0160000: # TODO : properly handle submodules and document what 57344 means continue if sha in seen: continue @@ -488,9 +527,9 @@ def convert_git_int_mode(self, mode): # TODO : make these into constants convert = { - 33188: '', - 40960: 'l', - 33261: 'x'} + 0100644: '', + 0100755: 'x', + 0120000: 'l'} if mode in convert: return convert[mode] return '' @@ -517,8 +556,8 @@ def pseudo_import_git_commit(self, commit): (strip_message, hg_renames, hg_branch) = self.extract_hg_metadata(commit.message) cs = self.map_hg_get(commit.id) - p1 = "0" * 40 - p2 = "0" * 40 + p1 = nullid + p2 = nullid if len(commit.parents) > 0: sha = commit.parents[0] p1 = self.map_hg_get(sha) @@ -529,7 +568,7 @@ # TODO : map extra parents to the extras file pass # saving rename info - if (not (p2 == "0"*40) or (p1 == "0"*40)): + if (not (p2 == nullid) or (p1 == nullid)): self.renames[cs] = {} else: self.renames[cs] = self.renames[p1].copy() @@ -559,8 +598,8 @@ copied_path = None return context.memfilectx(f, data, 'l' in e, 'x' in e, copied_path) - p1 = "0" * 40 - p2 = "0" * 40 + p1 = nullid + p2 = nullid if len(commit.parents) > 0: sha = commit.parents[0] p1 = self.map_hg_get(sha) @@ -575,7 +614,7 @@ files = self.git.get_files_changed(commit) # wierd hack for explicit file renames in first but not second branch - if not (p2 == "0"*40): + if not (p2 == nullid): vals = [item for item in self.renames[p1].values() if not item in self.renames[p2].values()] for removefile in vals: files.remove(removefile) @@ -608,7 +647,7 @@ gitsha = commit.id # saving rename info - if (not (p2 == "0"*40) or (p1 == "0"*40)): + if (not (p2 == nullid) or (p1 == nullid)): self.renames[cs] = {} else: self.renames[cs] = self.renames[p1].copy()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-empty-working-tree Tue May 19 09:40:54 2009 -0700 @@ -0,0 +1,42 @@ +#!/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 && exit 80 + +echo "[extensions]" >> $HGRCPATH +echo "hggit=$(echo $(dirname $(dirname $0)))" >> $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 + +mkdir gitrepo +cd gitrepo +git init | python -c "import sys; print sys.stdin.read().replace('$(dirname $(pwd))/', '')" + +git commit --allow-empty -m empty + +# dulwich does not presently support local git repos, workaround +cd .. +git daemon --base-path="$(pwd)"\ + --listen=localhost\ + --export-all\ + --pid-file=gitdaemon.pid \ + --detach --reuseaddr + +hg gclone git://localhost/gitrepo hgrepo +cd hgrepo +hg log -r tip --template 'files: {files}\n' + +hg gclear +hg gexport + +cd .. +kill `cat gitdaemon.pid`
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-empty-working-tree.out Tue May 19 09:40:54 2009 -0700 @@ -0,0 +1,14 @@ +Initialized empty Git repository in gitrepo/.git/ + +[master (root-commit) 6782568] empty +fetching from : origin +exporting git objects +Counting objects: 2, done. +Total 2 (delta 0), reused 0 (delta 0) +importing Git objects into Hg +0 files updated, 0 files merged, 0 files removed, 0 files unresolved +files: +clearing out the git cache data +exporting git objects +at: 0/1 +converting revision 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-tree-decomposition Tue May 19 09:40:54 2009 -0700 @@ -0,0 +1,55 @@ +#!/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 && exit 80 + +echo "[extensions]" >> $HGRCPATH +echo "hggit=$(echo $(dirname $(dirname $0)))" >> $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))/', '')" + +mkdir d1 +touch d1/f1 d1/f2 +git add d1/f1 d1/f2 +git commit -m initial + +mkdir d2 +git mv d1/f2 d2/f2 +git commit -m 'rename' + +# dulwich does not presently support local git repos, workaround +cd .. +git daemon --base-path="$(pwd)"\ + --listen=localhost\ + --export-all\ + --pid-file=gitdaemon.pid \ + --detach --reuseaddr + +hg gclone git://localhost/gitrepo hgrepo +cd hgrepo +hg log -r tip --template 'adds: {file_adds}\ndels: {file_dels}\n' + +cd .. +kill `cat gitdaemon.pid`
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-tree-decomposition.out Tue May 19 09:40:54 2009 -0700 @@ -0,0 +1,18 @@ +Initialized empty Git repository in gitrepo/.git/ + +[master (root-commit) 60fd61f] initial + 0 files changed, 0 insertions(+), 0 deletions(-) + create mode 100644 d1/f1 + create mode 100644 d1/f2 +[master a2e8665] rename + 1 files changed, 0 insertions(+), 0 deletions(-) + rename {d1 => d2}/f2 (100%) +fetching from : origin +exporting git objects +Counting objects: 8, done. +Compressing objects: 25% (1/4) Compressing objects: 50% (2/4) Compressing objects: 75% (3/4) Compressing objects: 100% (4/4) Compressing objects: 100% (4/4), done. +Total 8 (delta 0), reused 0 (delta 0) +importing Git objects into Hg +2 files updated, 0 files merged, 0 files removed, 0 files unresolved +adds: d2/f2 +dels: d1/f2