mirror of
				https://github.com/mnauw/git-remote-hg.git
				synced 2025-10-31 08:35:48 +01:00 
			
		
		
		
	Compare commits
	
		
			50 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | b6e9475918 | ||
|  | 517ceb91ac | ||
|  | 114804f0cb | ||
|  | b022367aef | ||
|  | 18626d346f | ||
|  | b81ec14c2e | ||
|  | 1e279075dc | ||
|  | 02a0a59a4b | ||
|  | 185852eac4 | ||
|  | 29a0d8a0e3 | ||
|  | aa528c9649 | ||
|  | 018aa4753b | ||
|  | f173208406 | ||
|  | e7df347fab | ||
|  | 0de8aa91f4 | ||
|  | 22d9794c11 | ||
|  | f53a8653ab | ||
|  | b4c63539f2 | ||
|  | 38070007aa | ||
|  | fadd5f698b | ||
|  | 1eb8fa4805 | ||
|  | 19f31c1c84 | ||
|  | ff221de459 | ||
|  | 179fefda96 | ||
|  | c226ba3904 | ||
|  | 776e36c147 | ||
|  | 5b6d5283cb | ||
|  | 5738ee42d8 | ||
|  | 1d27390dd0 | ||
|  | cad5c95465 | ||
|  | 259838a342 | ||
|  | 55bbd81a75 | ||
|  | 8db5b9a537 | ||
|  | bbc4009acf | ||
|  | c84feb364b | ||
|  | 990152c0c8 | ||
|  | 6ba42cdf98 | ||
|  | ef00e40d7c | ||
|  | 1c72617831 | ||
|  | 184551c71d | ||
|  | 32d4f36f22 | ||
|  | ccb3f13d69 | ||
|  | 2958556bec | ||
|  | 4ea2fa76b3 | ||
|  | 84b8b482a4 | ||
|  | 978314a4be | ||
|  | 51eabd4a17 | ||
|  | 98c3535c3f | ||
|  | 3abf376e9e | ||
|  | 0b71ca38e7 | 
							
								
								
									
										28
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | language: python | ||||||
|  |  | ||||||
|  | install: | ||||||
|  |   - if [ "$HG_VERSION" != "dev" ]; | ||||||
|  |     then pip install -q Mercurial${HG_VERSION+==$HG_VERSION}; | ||||||
|  |     else pip install -q http://selenic.com/repo/hg/archive/tip.tar.gz; | ||||||
|  |     fi | ||||||
|  |   - pip install -q dulwich hg-git==0.6.1 || true | ||||||
|  |  | ||||||
|  | before_script: | ||||||
|  |   - hg --version || true | ||||||
|  |   - pip show hg-git dulwich | ||||||
|  |  | ||||||
|  | script: | ||||||
|  |   - make test | ||||||
|  |  | ||||||
|  | matrix: | ||||||
|  |   include: | ||||||
|  |     - env: HG_VERSION=2.9.1 | ||||||
|  |     - env: HG_VERSION=2.8.2 | ||||||
|  |     - env: HG_VERSION=2.7.2 | ||||||
|  |     - env: HG_VERSION=3.0 | ||||||
|  |     - env: HG_VERSION=3.5.2 | ||||||
|  |     - env: HG_VERSION=3.6.3 | ||||||
|  |     - env: HG_VERSION=3.7 | ||||||
|  |     - env: HG_VERSION=dev | ||||||
|  |     - python: 2.7 | ||||||
|  |     - python: 2.6 | ||||||
							
								
								
									
										27
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,6 +1,29 @@ | |||||||
| all: | prefix := $(HOME) | ||||||
|  |  | ||||||
|  | bindir := $(prefix)/bin | ||||||
|  | mandir := $(prefix)/share/man/man1 | ||||||
|  |  | ||||||
|  | all: doc | ||||||
|  |  | ||||||
|  | doc: doc/git-remote-hg.1 | ||||||
|  |  | ||||||
| test: | test: | ||||||
| 	$(MAKE) -C test | 	$(MAKE) -C test | ||||||
|  |  | ||||||
| .PHONY: all test | doc/git-remote-hg.1: doc/git-remote-hg.txt | ||||||
|  | 	a2x -d manpage -f manpage $< | ||||||
|  |  | ||||||
|  | clean: | ||||||
|  | 	$(RM) doc/git-remote-hg.1 | ||||||
|  |  | ||||||
|  | D = $(DESTDIR) | ||||||
|  |  | ||||||
|  | install: | ||||||
|  | 	install -d -m 755 $(D)$(bindir)/ | ||||||
|  | 	install -m 755 git-remote-hg $(D)$(bindir)/git-remote-hg | ||||||
|  |  | ||||||
|  | install-doc: doc | ||||||
|  | 	install -d -m 755 $(D)$(mandir)/ | ||||||
|  | 	install -m 644 doc/git-remote-hg.1 $(D)$(mandir)/git-remote-hg.1 | ||||||
|  |  | ||||||
|  | .PHONY: all test install install-doc clean | ||||||
|   | |||||||
							
								
								
									
										131
									
								
								README.asciidoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								README.asciidoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | 'git-remote-hg' is the semi-official Mercurial bridge from Git project, once | ||||||
|  | installed, it allows you to clone, fetch and push to and from Mercurial | ||||||
|  | repositories as if they were Git ones: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | git clone "hg::http://selenic.com/repo/hello" | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | To enable this, simply add the 'git-remote-hg' script anywhere in your `$PATH`: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | wget https://raw.github.com/felipec/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg | ||||||
|  | chmod +x ~/bin/git-remote-hg | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | That's it :) | ||||||
|  |  | ||||||
|  | Obviously you will need Mercurial installed. | ||||||
|  |  | ||||||
|  | == Configuration == | ||||||
|  |  | ||||||
|  | If you want to see Mercurial revisions as Git commit notes: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config core.notesRef refs/notes/hg | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | If you are not interested in Mercurial permanent and global branches (aka. commit labels): | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config --global remote-hg.track-branches false | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | With this configuration, the 'branches/foo' refs won't appear. | ||||||
|  |  | ||||||
|  | If you want the equivalent of 'hg clone --insecure': | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config --global remote-hg.insecure true | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly the same commits: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config --global remote-hg.hg-git-compat true | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | == Notes == | ||||||
|  |  | ||||||
|  | Remember to run `git gc --aggressive` after cloning a repository, specially if | ||||||
|  | it's a big one. Otherwise lots of space will be wasted. | ||||||
|  |  | ||||||
|  | The oldest version of mercurial supported is 1.9. For the most part 1.8 works, | ||||||
|  | but you might experience some issues. | ||||||
|  |  | ||||||
|  | === Pushing branches === | ||||||
|  |  | ||||||
|  | To push a branch, you need to use the "branches/" prefix: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git checkout branches/next | ||||||
|  | # do stuff | ||||||
|  | % git push origin branches/next | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | All the pushed commits will receive the "next" Mercurial named branch. | ||||||
|  |  | ||||||
|  | *Note*: Make sure you don't have +remote-hg.track-branches+ disabled. | ||||||
|  |  | ||||||
|  | === Cloning HTTPS === | ||||||
|  |  | ||||||
|  | The simplest way is to specify the user and password in the URL: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | git clone hg::https://user:password@bitbucket.org/user/repo | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | You can also use the http://mercurial.selenic.com/wiki/SchemesExtension[schemes extension]: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | [auth] | ||||||
|  | bb.prefix = https://bitbucket.org/user/ | ||||||
|  | bb.username = user | ||||||
|  | bb.password = password | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | Finally, you can also use the | ||||||
|  | https://pypi.python.org/pypi/mercurial_keyring[keyring extension]. | ||||||
|  |  | ||||||
|  | However, some of these features require very new versions of 'git-remote-hg', | ||||||
|  | so you might have better luck simply specifying the username and password in | ||||||
|  | the URL. | ||||||
|  |  | ||||||
|  | === Caveats === | ||||||
|  |  | ||||||
|  | The only major incompatibility is that Git octopus merges (a merge with more | ||||||
|  | than two parents) are not supported. | ||||||
|  |  | ||||||
|  | Mercurial branches and bookmarks have some limitations of Git branches: you | ||||||
|  | can't have both 'dev/feature' and 'dev' (as Git uses files and directories to | ||||||
|  | store them). | ||||||
|  |  | ||||||
|  | Multiple anonymous heads (which are useless anyway) are not supported; you | ||||||
|  | would only see the latest head. | ||||||
|  |  | ||||||
|  | Closed branches are not supported; they are not shown and you can't close or | ||||||
|  | reopen. Additionally in certain rare situations a synchronization issue can | ||||||
|  | occur (https://github.com/felipec/git/issues/65[Bug #65]). | ||||||
|  |  | ||||||
|  | Limitations of the remote-helpers' framework apply. In particular, these | ||||||
|  | commands don't work: | ||||||
|  |  | ||||||
|  | * `git push origin :branch-to-delete` | ||||||
|  | * `git push origin old:new` (it will push 'old') (patches available) | ||||||
|  | * `git push --dry-run origin branch` (it will push) (patches available) | ||||||
|  |  | ||||||
|  | == Other projects == | ||||||
|  |  | ||||||
|  | There are other 'git-remote-hg' projects out there, do not confuse this one, | ||||||
|  | this is the one distributed officially by the Git project: | ||||||
|  |  | ||||||
|  | * https://github.com/msysgit/msysgit/wiki/Guide-to-git-remote-hg[msysgit's git-remote-hg] | ||||||
|  | * https://github.com/rfk/git-remote-hg[rfk's git-remote-hg] | ||||||
|  |  | ||||||
|  | For a comparison between these and other projects go | ||||||
|  | https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives[here]. | ||||||
|  |  | ||||||
|  | == Contributing == | ||||||
|  |  | ||||||
|  | Send your patches to the mailing list git-fc@googlegroups.com (no need to | ||||||
|  | subscribe). | ||||||
							
								
								
									
										1
									
								
								doc/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								doc/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | git-remote-hg.1 | ||||||
							
								
								
									
										5
									
								
								doc/SubmittingPatches
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								doc/SubmittingPatches
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | Please send your patches using `git format-patch` to the mailing list: | ||||||
|  | git-fc@googlegroups.com. | ||||||
|  |  | ||||||
|  | Make sure all the tests pass by running `make test`, and if possible add a new | ||||||
|  | test to exercise the code you are submitting. | ||||||
							
								
								
									
										121
									
								
								doc/git-remote-hg.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								doc/git-remote-hg.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | git-remote-hg(1) | ||||||
|  | ================ | ||||||
|  |  | ||||||
|  | NAME | ||||||
|  | ---- | ||||||
|  | git-remote-hg - bidirectional bridge between Git and Mercurial | ||||||
|  |  | ||||||
|  |  | ||||||
|  | SYNOPSIS | ||||||
|  | -------- | ||||||
|  | [verse] | ||||||
|  | 'git clone' hg::<hg repository> | ||||||
|  |  | ||||||
|  |  | ||||||
|  | DESCRIPTION | ||||||
|  | ----------- | ||||||
|  |  | ||||||
|  | This tool allows you to transparently clone, fetch and push to and from Mercurial | ||||||
|  | repositories as if they were Git ones. | ||||||
|  |  | ||||||
|  | To use it you simply need to use the "'hg::'" prefix when specifying a remote URL | ||||||
|  | (e.g. when cloning). | ||||||
|  |  | ||||||
|  |  | ||||||
|  | EXAMPLE | ||||||
|  | ------- | ||||||
|  | ------------ | ||||||
|  | $ git clone hg::http://selenic.com/repo/hello | ||||||
|  | ------------ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CONFIGURATION | ||||||
|  | ------------- | ||||||
|  |  | ||||||
|  | If you want to see Mercurial revisions as Git commit notes: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config core.notesRef refs/notes/hg | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | If you are not interested in Mercurial permanent and global branches (aka. commit labels): | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config --global remote-hg.track-branches false | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | With this configuration, the 'branches/foo' refs won't appear. | ||||||
|  |  | ||||||
|  | If you want the equivalent of `hg clone --insecure`: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config --global remote-hg.insecure true | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly the same commits: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git config --global remote-hg.hg-git-compat true | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | NOTES | ||||||
|  | ----- | ||||||
|  |  | ||||||
|  | Remember to run `git gc --aggressive` after cloning a repository, specially if | ||||||
|  | it's a big one. Otherwise lots of space will be wasted. | ||||||
|  |  | ||||||
|  | The oldest version of Mercurial supported is 1.9. For the most part 1.8 works, | ||||||
|  | but you might experience some issues. | ||||||
|  |  | ||||||
|  | Pushing branches | ||||||
|  | ~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | To push a Mercurial named branch, you need to use the "branches/" prefix: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | % git checkout branches/next | ||||||
|  | # do stuff | ||||||
|  | % git push origin branches/next | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | All the pushed commits will receive the "next" Mercurial named branch. | ||||||
|  |  | ||||||
|  | *Note*: Make sure you don't have +remote-hg.track-branches+ disabled. | ||||||
|  |  | ||||||
|  | Cloning HTTPS | ||||||
|  | ~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | The simplest way is to specify the user and password in the URL: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | git clone hg::https://user:password@bitbucket.org/user/repo | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | You can also use the http://mercurial.selenic.com/wiki/SchemesExtension[schemes extension]: | ||||||
|  |  | ||||||
|  | -------------------------------------- | ||||||
|  | [auth] | ||||||
|  | bb.prefix = https://bitbucket.org/user/ | ||||||
|  | bb.username = user | ||||||
|  | bb.password = password | ||||||
|  | -------------------------------------- | ||||||
|  |  | ||||||
|  | Finally, you can also use the | ||||||
|  | https://pypi.python.org/pypi/mercurial_keyring[keyring extension]. | ||||||
|  |  | ||||||
|  | CAVEATS | ||||||
|  | ------- | ||||||
|  |  | ||||||
|  | The only major incompatibility is that Git octopus merges (a merge with more | ||||||
|  | than two parents) are not supported. | ||||||
|  |  | ||||||
|  | Mercurial branches and bookmarks have some limitations of Git branches: you | ||||||
|  | can't have both 'dev/feature' and 'dev' (as Git uses files and directories to | ||||||
|  | store them). | ||||||
|  |  | ||||||
|  | Multiple anonymous heads (which are useless anyway) are not supported; you | ||||||
|  | would only see the latest head. | ||||||
|  |  | ||||||
|  | Closed branches are not supported; they are not shown and you can't close or | ||||||
|  | reopen. Additionally in certain rare situations a synchronization issue can | ||||||
|  | occur (https://github.com/felipec/git/issues/65[Bug #65]). | ||||||
							
								
								
									
										133
									
								
								git-remote-hg
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								git-remote-hg
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | |||||||
| #!/usr/bin/env python | #!/usr/bin/env python2 | ||||||
| # | # | ||||||
| # Copyright (c) 2012 Felipe Contreras | # Copyright (c) 2012 Felipe Contreras | ||||||
| # | # | ||||||
| @@ -12,7 +12,9 @@ | |||||||
| # For remote repositories a local clone is stored in | # For remote repositories a local clone is stored in | ||||||
| # "$GIT_DIR/hg/origin/clone/.hg/". | # "$GIT_DIR/hg/origin/clone/.hg/". | ||||||
|  |  | ||||||
| from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions, discovery, util | from mercurial import hg, ui, bookmarks, context, encoding | ||||||
|  | from mercurial import node, error, extensions, discovery, util | ||||||
|  | from mercurial import changegroup | ||||||
|  |  | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| @@ -22,7 +24,8 @@ import shutil | |||||||
| import subprocess | import subprocess | ||||||
| import urllib | import urllib | ||||||
| import atexit | import atexit | ||||||
| import urlparse, hashlib | import urlparse | ||||||
|  | import hashlib | ||||||
| import time as ptime | import time as ptime | ||||||
|  |  | ||||||
| # | # | ||||||
| @@ -53,7 +56,7 @@ import time as ptime | |||||||
| NAME_RE = re.compile('^([^<>]+)') | NAME_RE = re.compile('^([^<>]+)') | ||||||
| AUTHOR_RE = re.compile('^([^<>]+?)? ?[<>]([^<>]*)(?:$|>)') | AUTHOR_RE = re.compile('^([^<>]+?)? ?[<>]([^<>]*)(?:$|>)') | ||||||
| EMAIL_RE = re.compile(r'([^ \t<>]+@[^ \t<>]+)') | EMAIL_RE = re.compile(r'([^ \t<>]+@[^ \t<>]+)') | ||||||
| AUTHOR_HG_RE = re.compile('^(.*?) ?<(.*?)(?:>(.+)?)?$') | AUTHOR_HG_RE = re.compile('^(.*?) ?<(.*?)(?:>(.*))?$') | ||||||
| RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)') | RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)') | ||||||
|  |  | ||||||
| VERSION = 2 | VERSION = 2 | ||||||
| @@ -156,7 +159,9 @@ class Marks: | |||||||
|         self.version = 2 |         self.version = 2 | ||||||
|  |  | ||||||
|     def dict(self): |     def dict(self): | ||||||
|         return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version, 'last-note' : self.last_note } |         return { 'tips': self.tips, 'marks': self.marks, | ||||||
|  |                 'last-mark': self.last_mark, 'version': self.version, | ||||||
|  |                 'last-note': self.last_note } | ||||||
|  |  | ||||||
|     def store(self): |     def store(self): | ||||||
|         json.dump(self.dict(), open(self.path, 'w')) |         json.dump(self.dict(), open(self.path, 'w')) | ||||||
| @@ -260,6 +265,7 @@ class Parser: | |||||||
|         return (user, int(date), -tz) |         return (user, int(date), -tz) | ||||||
|  |  | ||||||
| def fix_file_path(path): | def fix_file_path(path): | ||||||
|  |     path = os.path.normpath(path) | ||||||
|     if not os.path.isabs(path): |     if not os.path.isabs(path): | ||||||
|         return path |         return path | ||||||
|     return os.path.relpath(path, '/') |     return os.path.relpath(path, '/') | ||||||
| @@ -421,9 +427,14 @@ def get_repo(url, alias): | |||||||
|  |  | ||||||
|         repo = hg.repository(myui, local_path) |         repo = hg.repository(myui, local_path) | ||||||
|         try: |         try: | ||||||
|             peer = hg.peer(myui, {}, url) |             peer = hg.peer(repo.ui, {}, url) | ||||||
|         except: |         except: | ||||||
|             die('Repository error') |             die('Repository error') | ||||||
|  |  | ||||||
|  |         if check_version(3, 0): | ||||||
|  |             from mercurial import exchange | ||||||
|  |             exchange.pull(repo, peer, heads=None, force=True) | ||||||
|  |         else: | ||||||
|             repo.pull(peer, heads=None, force=True) |             repo.pull(peer, heads=None, force=True) | ||||||
|  |  | ||||||
|         updatebookmarks(repo, peer) |         updatebookmarks(repo, peer) | ||||||
| @@ -436,16 +447,46 @@ def rev_to_mark(rev): | |||||||
| def mark_to_rev(mark): | def mark_to_rev(mark): | ||||||
|     return marks.to_rev(mark) |     return marks.to_rev(mark) | ||||||
|  |  | ||||||
|  | # Get a range of revisions in the form of a..b (git committish) | ||||||
|  | def gitrange(repo, a, b): | ||||||
|  |     positive = [] | ||||||
|  |     pending = set([int(b)]) | ||||||
|  |     negative = set([int(a)]) | ||||||
|  |     for cur in xrange(b, -1, -1): | ||||||
|  |         if not pending: | ||||||
|  |             break | ||||||
|  |  | ||||||
|  |         parents = [p for p in repo.changelog.parentrevs(cur) if p >= 0] | ||||||
|  |  | ||||||
|  |         if cur in pending: | ||||||
|  |             positive.append(cur) | ||||||
|  |             pending.remove(cur) | ||||||
|  |             for p in parents: | ||||||
|  |                 if p not in negative: | ||||||
|  |                     pending.add(p) | ||||||
|  |         elif cur in negative: | ||||||
|  |             negative.remove(cur) | ||||||
|  |             for p in parents: | ||||||
|  |                 if p not in pending: | ||||||
|  |                     negative.add(p) | ||||||
|  |                 else: | ||||||
|  |                     pending.discard(p) | ||||||
|  |  | ||||||
|  |     positive.reverse() | ||||||
|  |     return positive | ||||||
|  |  | ||||||
| def export_ref(repo, name, kind, head): | def export_ref(repo, name, kind, head): | ||||||
|     ename = '%s/%s' % (kind, name) |     ename = '%s/%s' % (kind, name) | ||||||
|     try: |     try: | ||||||
|         tip = marks.get_tip(ename) |         tip = marks.get_tip(ename) | ||||||
|         tip = repo[tip].rev() |         tip = repo[tip] | ||||||
|     except: |     except: | ||||||
|         tip = 0 |         tip = repo[-1] | ||||||
|  |  | ||||||
|  |     revs = gitrange(repo, tip, head) | ||||||
|  |  | ||||||
|     revs = xrange(tip, head.rev() + 1) |  | ||||||
|     total = len(revs) |     total = len(revs) | ||||||
|  |     tip = tip.rev() | ||||||
|  |  | ||||||
|     for rev in revs: |     for rev in revs: | ||||||
|  |  | ||||||
| @@ -460,8 +501,12 @@ def export_ref(repo, name, kind, head): | |||||||
|  |  | ||||||
|         author = "%s %d %s" % (fixup_user(user), time, gittz(tz)) |         author = "%s %d %s" % (fixup_user(user), time, gittz(tz)) | ||||||
|         if 'committer' in extra: |         if 'committer' in extra: | ||||||
|             user, time, tz = extra['committer'].rsplit(' ', 2) |             try: | ||||||
|             committer = "%s %s %s" % (user, time, gittz(int(tz))) |                 cuser, ctime, ctz = extra['committer'].rsplit(' ', 2) | ||||||
|  |                 committer = "%s %s %s" % (fixup_user(cuser), ctime, gittz(int(ctz))) | ||||||
|  |             except ValueError: | ||||||
|  |                 cuser = extra['committer'] | ||||||
|  |                 committer = "%s %d %s" % (fixup_user(cuser), time, gittz(tz)) | ||||||
|         else: |         else: | ||||||
|             committer = author |             committer = author | ||||||
|  |  | ||||||
| @@ -614,7 +659,7 @@ def list_head(repo, cur): | |||||||
|         return |         return | ||||||
|  |  | ||||||
|     node = repo[branch_tip('default')] |     node = repo[branch_tip('default')] | ||||||
|     head = 'master' if not 'master' in bmarks else 'default' |     head = 'master' if 'master' not in bmarks else 'default' | ||||||
|     fake_bmark = head |     fake_bmark = head | ||||||
|     bmarks[head] = node |     bmarks[head] = node | ||||||
|  |  | ||||||
| @@ -643,6 +688,9 @@ def do_list(parser): | |||||||
|             print "? refs/heads/branches/%s" % gitref(branch) |             print "? refs/heads/branches/%s" % gitref(branch) | ||||||
|  |  | ||||||
|     for bmark in bmarks: |     for bmark in bmarks: | ||||||
|  |         if bmarks[bmark].hex() == '0' * 40: | ||||||
|  |             warn("Ignoring invalid bookmark '%s'", bmark) | ||||||
|  |         else: | ||||||
|             print "? refs/heads/%s" % gitref(bmark) |             print "? refs/heads/%s" % gitref(bmark) | ||||||
|  |  | ||||||
|     for tag, node in repo.tagslist(): |     for tag, node in repo.tagslist(): | ||||||
| @@ -760,12 +808,30 @@ def parse_commit(parser): | |||||||
|     def getfilectx(repo, memctx, f): |     def getfilectx(repo, memctx, f): | ||||||
|         of = files[f] |         of = files[f] | ||||||
|         if 'deleted' in of: |         if 'deleted' in of: | ||||||
|  |             if check_version(3, 2): | ||||||
|  |                 return None | ||||||
|  |             else: | ||||||
|                 raise IOError |                 raise IOError | ||||||
|         if 'ctx' in of: |         if 'ctx' in of: | ||||||
|  |             if mode == 'hg': | ||||||
|  |                 ctx = of['ctx'] | ||||||
|  |                 is_exec = ctx.isexec() | ||||||
|  |                 is_link = ctx.islink() | ||||||
|  |                 if check_version(3, 1): | ||||||
|  |                     return context.memfilectx(repo, f, ctx.data(), | ||||||
|  |                             is_link, is_exec) | ||||||
|  |                 else: | ||||||
|  |                     return context.memfilectx(f, ctx.data(), | ||||||
|  |                             is_link, is_exec) | ||||||
|  |             else: | ||||||
|                 return of['ctx'] |                 return of['ctx'] | ||||||
|         is_exec = of['mode'] == 'x' |         is_exec = of['mode'] == 'x' | ||||||
|         is_link = of['mode'] == 'l' |         is_link = of['mode'] == 'l' | ||||||
|         rename = of.get('rename', None) |         rename = of.get('rename', None) | ||||||
|  |         if check_version(3, 1): | ||||||
|  |             return context.memfilectx(repo, f, of['data'], | ||||||
|  |                     is_link, is_exec, rename) | ||||||
|  |         else: | ||||||
|             return context.memfilectx(f, of['data'], |             return context.memfilectx(f, of['data'], | ||||||
|                     is_link, is_exec, rename) |                     is_link, is_exec, rename) | ||||||
|  |  | ||||||
| @@ -870,6 +936,9 @@ def write_tag(repo, tag, node, msg, author): | |||||||
|         except error.ManifestLookupError: |         except error.ManifestLookupError: | ||||||
|             data = "" |             data = "" | ||||||
|         content = data + "%s %s\n" % (node, tag) |         content = data + "%s %s\n" % (node, tag) | ||||||
|  |         if check_version(3, 1): | ||||||
|  |             return context.memfilectx(repo, f, content, False, False, None) | ||||||
|  |         else: | ||||||
|             return context.memfilectx(f, content, False, False, None) |             return context.memfilectx(f, content, False, False, None) | ||||||
|  |  | ||||||
|     p1 = tip.hex() |     p1 = tip.hex() | ||||||
| @@ -903,12 +972,17 @@ def write_tag(repo, tag, node, msg, author): | |||||||
|  |  | ||||||
| def checkheads_bmark(repo, ref, ctx): | def checkheads_bmark(repo, ref, ctx): | ||||||
|     bmark = ref[len('refs/heads/'):] |     bmark = ref[len('refs/heads/'):] | ||||||
|     if not bmark in bmarks: |     if bmark not in bmarks: | ||||||
|         # new bmark |         # new bmark | ||||||
|         return True |         return True | ||||||
|  |  | ||||||
|     ctx_old = bmarks[bmark] |     ctx_old = bmarks[bmark] | ||||||
|     ctx_new = ctx |     ctx_new = ctx | ||||||
|  |  | ||||||
|  |     if not ctx.rev(): | ||||||
|  |         print "error %s unknown" % ref | ||||||
|  |         return False | ||||||
|  |  | ||||||
|     if not repo.changelog.descendant(ctx_old.rev(), ctx_new.rev()): |     if not repo.changelog.descendant(ctx_old.rev(), ctx_new.rev()): | ||||||
|         if force_push: |         if force_push: | ||||||
|             print "ok %s forced update" % ref |             print "ok %s forced update" % ref | ||||||
| @@ -931,7 +1005,7 @@ def checkheads(repo, remote, p_revs): | |||||||
|     for node, ref in p_revs.iteritems(): |     for node, ref in p_revs.iteritems(): | ||||||
|         ctx = repo[node] |         ctx = repo[node] | ||||||
|         branch = ctx.branch() |         branch = ctx.branch() | ||||||
|         if not branch in remotemap: |         if branch not in remotemap: | ||||||
|             # new branch |             # new branch | ||||||
|             continue |             continue | ||||||
|         if not ref.startswith('refs/heads/branches'): |         if not ref.startswith('refs/heads/branches'): | ||||||
| @@ -981,15 +1055,28 @@ def push_unsafe(repo, remote, parsed_refs, p_revs): | |||||||
|     if not checkheads(repo, remote, p_revs): |     if not checkheads(repo, remote, p_revs): | ||||||
|         return None |         return None | ||||||
|  |  | ||||||
|  |     if check_version(3, 2): | ||||||
|  |         cg = changegroup.getchangegroup(repo, 'push', heads=list(p_revs), common=common) | ||||||
|  |     elif check_version(3, 0): | ||||||
|  |         cg = changegroup.getbundle(repo, 'push', heads=list(p_revs), common=common) | ||||||
|  |     else: | ||||||
|         cg = repo.getbundle('push', heads=list(p_revs), common=common) |         cg = repo.getbundle('push', heads=list(p_revs), common=common) | ||||||
|  |  | ||||||
|     unbundle = remote.capable('unbundle') |     unbundle = remote.capable('unbundle') | ||||||
|     if unbundle: |     if unbundle: | ||||||
|         if force: |         if force: | ||||||
|             remoteheads = ['force'] |             remoteheads = ['force'] | ||||||
|         return remote.unbundle(cg, remoteheads, 'push') |         ret = remote.unbundle(cg, remoteheads, 'push') | ||||||
|     else: |     else: | ||||||
|         return remote.addchangegroup(cg, 'push', repo.url()) |         ret = remote.addchangegroup(cg, 'push', repo.url()) | ||||||
|  |  | ||||||
|  |     phases = remote.listkeys('phases') | ||||||
|  |     if phases: | ||||||
|  |         for head in p_revs: | ||||||
|  |             # update to public | ||||||
|  |             remote.pushkey('phases', hghex(head), '1', '0') | ||||||
|  |  | ||||||
|  |     return ret | ||||||
|  |  | ||||||
| def push(repo, remote, parsed_refs, p_revs): | def push(repo, remote, parsed_refs, p_revs): | ||||||
|     if hasattr(remote, 'canpush') and not remote.canpush(): |     if hasattr(remote, 'canpush') and not remote.canpush(): | ||||||
| @@ -1207,7 +1294,11 @@ def main(args): | |||||||
|     filenodes = {} |     filenodes = {} | ||||||
|     fake_bmark = None |     fake_bmark = None | ||||||
|     try: |     try: | ||||||
|         hg_version = tuple(int(e) for e in util.version().split('.')) |         version, _, extra = util.version().partition('+') | ||||||
|  |         version = list(int(e) for e in version.split('.')) | ||||||
|  |         if extra: | ||||||
|  |             version[1] += 1 | ||||||
|  |         hg_version = tuple(version) | ||||||
|     except: |     except: | ||||||
|         hg_version = None |         hg_version = None | ||||||
|     dry_run = False |     dry_run = False | ||||||
| @@ -1242,12 +1333,10 @@ def main(args): | |||||||
|             die('unhandled command: %s' % line) |             die('unhandled command: %s' % line) | ||||||
|         sys.stdout.flush() |         sys.stdout.flush() | ||||||
|  |  | ||||||
| def bye(): |  | ||||||
|     if not marks: |  | ||||||
|         return |  | ||||||
|     if not is_tmp: |  | ||||||
|     marks.store() |     marks.store() | ||||||
|     else: |  | ||||||
|  | def bye(): | ||||||
|  |     if is_tmp: | ||||||
|         shutil.rmtree(dirname) |         shutil.rmtree(dirname) | ||||||
|  |  | ||||||
| atexit.register(bye) | atexit.register(bye) | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | test-results/ | ||||||
|  | trash directory.*/ | ||||||
|  | .prove | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| RM ?= rm -f | RM ?= rm -f | ||||||
|  |  | ||||||
| T = $(wildcard ../test-*.sh) | T = main.t bidi.t | ||||||
| TEST_DIRECTORY := $(CURDIR) | TEST_DIRECTORY := $(CURDIR) | ||||||
|  |  | ||||||
| export TEST_DIRECTORY | export TEST_DIRECTORY | ||||||
|   | |||||||
| @@ -8,7 +8,8 @@ | |||||||
| 
 | 
 | ||||||
| test_description='Test bidirectionality of remote-hg' | test_description='Test bidirectionality of remote-hg' | ||||||
| 
 | 
 | ||||||
| . ./test-lib.sh | test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||||
|  | . "$TEST_DIRECTORY"/test-lib.sh | ||||||
| 
 | 
 | ||||||
| if ! test_have_prereq PYTHON | if ! test_have_prereq PYTHON | ||||||
| then | then | ||||||
| @@ -16,7 +17,7 @@ then | |||||||
| 	test_done | 	test_done | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| if ! python -c 'import mercurial' | if ! python2 -c 'import mercurial' > /dev/null 2>&1 | ||||||
| then | then | ||||||
| 	skip_all='skipping remote-hg tests; mercurial not available' | 	skip_all='skipping remote-hg tests; mercurial not available' | ||||||
| 	test_done | 	test_done | ||||||
| @@ -54,17 +55,17 @@ hg_log () { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| setup () { | setup () { | ||||||
| 	( | 	cat > "$HOME"/.hgrc <<-EOF && | ||||||
| 	echo "[ui]" | 	[ui] | ||||||
| 	echo "username = A U Thor <author@example.com>" | 	username = A U Thor <author@example.com> | ||||||
| 	echo "[defaults]" | 	[defaults] | ||||||
| 	echo "backout = -d \"0 0\"" | 	backout = -d "0 0" | ||||||
| 	echo "commit = -d \"0 0\"" | 	commit = -d "0 0" | ||||||
| 	echo "debugrawcommit = -d \"0 0\"" | 	debugrawcommit = -d "0 0" | ||||||
| 	echo "tag = -d \"0 0\"" | 	tag = -d "0 0" | ||||||
| 	echo "[extensions]" | 	[extensions]" | ||||||
| 	echo "graphlog =" | 	graphlog = | ||||||
| 	) >>"$HOME"/.hgrc && | 	EOF | ||||||
| 	git config --global remote-hg.hg-git-compat true | 	git config --global remote-hg.hg-git-compat true | ||||||
| 	git config --global remote-hg.track-branches true | 	git config --global remote-hg.track-branches true | ||||||
| 
 | 
 | ||||||
| @@ -8,7 +8,8 @@ | |||||||
| 
 | 
 | ||||||
| test_description='Test remote-hg output compared to hg-git' | test_description='Test remote-hg output compared to hg-git' | ||||||
| 
 | 
 | ||||||
| . ./test-lib.sh | test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||||
|  | . "$TEST_DIRECTORY"/test-lib.sh | ||||||
| 
 | 
 | ||||||
| if ! test_have_prereq PYTHON | if ! test_have_prereq PYTHON | ||||||
| then | then | ||||||
| @@ -16,18 +17,32 @@ then | |||||||
| 	test_done | 	test_done | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| if ! python -c 'import mercurial' | if ! python2 -c 'import mercurial' > /dev/null 2>&1 | ||||||
| then | then | ||||||
| 	skip_all='skipping remote-hg tests; mercurial not available' | 	skip_all='skipping remote-hg tests; mercurial not available' | ||||||
| 	test_done | 	test_done | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| if ! python -c 'import hggit' | if python2 -c 'import hggit' > /dev/null 2>&1 | ||||||
| then | then | ||||||
|  | 	hggit=hggit | ||||||
|  | elif python2 -c 'import hgext.git' > /dev/null 2>&1 | ||||||
|  | then | ||||||
|  | 	hggit=hgext.git | ||||||
|  | else | ||||||
| 	skip_all='skipping remote-hg tests; hg-git not available' | 	skip_all='skipping remote-hg tests; hg-git not available' | ||||||
| 	test_done | 	test_done | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
|  | hg_version=$(python2 -c 'from mercurial import util; print util.version()') | ||||||
|  | 
 | ||||||
|  | case $hg_version in | ||||||
|  | 3.0*+*) | ||||||
|  | 	skip_all='skipping remote-hg tests; unsuported version of hg by hg-git' | ||||||
|  | 	test_done | ||||||
|  | 	;; | ||||||
|  | esac | ||||||
|  | 
 | ||||||
| # clone to a git repo with git | # clone to a git repo with git | ||||||
| git_clone_git () { | git_clone_git () { | ||||||
| 	git clone -q "hg::$1" $2 && | 	git clone -q "hg::$1" $2 && | ||||||
| @@ -91,19 +106,18 @@ git_log () { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| setup () { | setup () { | ||||||
| 	( | 	cat > "$HOME"/.hgrc <<-EOF && | ||||||
| 	echo "[ui]" | 	[ui] | ||||||
| 	echo "username = A U Thor <author@example.com>" | 	username = A U Thor <author@example.com> | ||||||
| 	echo "[defaults]" | 	[defaults] | ||||||
| 	echo "backout = -d \"0 0\"" | 	backout = -d "0 0" | ||||||
| 	echo "commit = -d \"0 0\"" | 	commit = -d "0 0" | ||||||
| 	echo "debugrawcommit = -d \"0 0\"" | 	debugrawcommit = -d "0 0" | ||||||
| 	echo "tag = -d \"0 0\"" | 	tag = -d "0 0" | ||||||
| 	echo "[extensions]" | 	[extensions] | ||||||
| 	echo "hgext.bookmarks =" | 	$hggit = | ||||||
| 	echo "hggit =" | 	graphlog = | ||||||
| 	echo "graphlog =" | 	EOF | ||||||
| 	) >>"$HOME"/.hgrc && |  | ||||||
| 	git config --global receive.denycurrentbranch warn | 	git config --global receive.denycurrentbranch warn | ||||||
| 	git config --global remote-hg.hg-git-compat true | 	git config --global remote-hg.hg-git-compat true | ||||||
| 	git config --global remote-hg.track-branches false | 	git config --global remote-hg.track-branches false | ||||||
| @@ -8,7 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| test_description='Test remote-hg' | test_description='Test remote-hg' | ||||||
| 
 | 
 | ||||||
| test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=${0%/*}/../../t | test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||||
| . "$TEST_DIRECTORY"/test-lib.sh | . "$TEST_DIRECTORY"/test-lib.sh | ||||||
| 
 | 
 | ||||||
| if ! test_have_prereq PYTHON | if ! test_have_prereq PYTHON | ||||||
| @@ -17,7 +17,7 @@ then | |||||||
| 	test_done | 	test_done | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| if ! python -c 'import mercurial' | if ! python2 -c 'import mercurial' > /dev/null 2>&1 | ||||||
| then | then | ||||||
| 	skip_all='skipping remote-hg tests; mercurial not available' | 	skip_all='skipping remote-hg tests; mercurial not available' | ||||||
| 	test_done | 	test_done | ||||||
| @@ -25,7 +25,7 @@ fi | |||||||
| 
 | 
 | ||||||
| check () { | check () { | ||||||
| 	echo $3 > expected && | 	echo $3 > expected && | ||||||
| 	git --git-dir=$1/.git log --format='%s' -1 $2 >actual | 	git --git-dir=$1/.git log --format='%s' -1 $2 > actual && | ||||||
| 	test_cmp expected actual | 	test_cmp expected actual | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @@ -53,6 +53,17 @@ check_bookmark () { | |||||||
| 	fi | 	fi | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | check_files () { | ||||||
|  | 	git --git-dir=$1/.git ls-files > actual && | ||||||
|  | 	if test $# -gt 1 | ||||||
|  | 	then | ||||||
|  | 		printf "%s\n" "$2" > expected | ||||||
|  | 	else | ||||||
|  | 		> expected | ||||||
|  | 	fi && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | } | ||||||
|  | 
 | ||||||
| check_push () { | check_push () { | ||||||
| 	expected_ret=$1 ret=0 ref_ret=0 | 	expected_ret=$1 ret=0 ref_ret=0 | ||||||
| 
 | 
 | ||||||
| @@ -92,12 +103,12 @@ check_push () { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| setup () { | setup () { | ||||||
| 	( | 	cat > "$HOME"/.hgrc <<-EOF && | ||||||
| 	echo "[ui]" | 	[ui] | ||||||
| 	echo "username = H G Wells <wells@example.com>" | 	username = H G Wells <wells@example.com> | ||||||
| 	echo "[extensions]" | 	[extensions] | ||||||
| 	echo "mq =" | 	mq = | ||||||
| 	) >>"$HOME"/.hgrc && | 	EOF | ||||||
| 
 | 
 | ||||||
| 	GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" && | 	GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" && | ||||||
| 	GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" && | 	GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" && | ||||||
| @@ -106,17 +117,18 @@ setup () { | |||||||
| 
 | 
 | ||||||
| setup | setup | ||||||
| 
 | 
 | ||||||
| test_expect_success 'cloning' ' | test_expect_success 'setup' ' | ||||||
| 	test_when_finished "rm -rf gitrepo*" && |  | ||||||
| 
 |  | ||||||
| 	( | 	( | ||||||
| 	hg init hgrepo && | 	hg init hgrepo && | ||||||
| 	cd hgrepo && | 	cd hgrepo && | ||||||
| 	echo zero > content && | 	echo zero > content && | ||||||
| 	hg add content && | 	hg add content && | ||||||
| 	hg commit -m zero | 	hg commit -m zero | ||||||
| 	) && | 	) | ||||||
|  | ' | ||||||
| 
 | 
 | ||||||
|  | test_expect_success 'cloning' ' | ||||||
|  | 	test_when_finished "rm -rf gitrepo*" && | ||||||
| 	git clone "hg::hgrepo" gitrepo && | 	git clone "hg::hgrepo" gitrepo && | ||||||
| 	check gitrepo HEAD zero | 	check gitrepo HEAD zero | ||||||
| ' | ' | ||||||
| @@ -772,4 +784,244 @@ test_expect_success 'remote double failed push' ' | |||||||
| 	) | 	) | ||||||
| ' | ' | ||||||
| 
 | 
 | ||||||
|  | test_expect_success 'clone remote with null bookmark, then push' ' | ||||||
|  | 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo a > a && | ||||||
|  | 	hg add a && | ||||||
|  | 	hg commit -m a && | ||||||
|  | 	hg bookmark -r null bookmark | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	check gitrepo HEAD a && | ||||||
|  | 	cd gitrepo && | ||||||
|  | 	git checkout --quiet -b bookmark && | ||||||
|  | 	git remote -v && | ||||||
|  | 	echo b > b && | ||||||
|  | 	git add b && | ||||||
|  | 	git commit -m b && | ||||||
|  | 	git push origin bookmark | ||||||
|  | 	) | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'notes' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo one > content && | ||||||
|  | 	hg add content && | ||||||
|  | 	hg commit -m one && | ||||||
|  | 	echo two > content && | ||||||
|  | 	hg commit -m two | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	hg -R hgrepo log --template "{node}\n\n" > expected && | ||||||
|  | 	git --git-dir=gitrepo/.git log --pretty="tformat:%N" --notes=hg > actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_failure 'push updates notes' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo one > content && | ||||||
|  | 	hg add content && | ||||||
|  | 	hg commit -m one | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	cd gitrepo && | ||||||
|  | 	echo two > content && | ||||||
|  | 	git commit -a -m two | ||||||
|  | 	git push | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	hg -R hgrepo log --template "{node}\n\n" > expected && | ||||||
|  | 	git --git-dir=gitrepo/.git log --pretty="tformat:%N" --notes=hg > actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'pull tags' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo one > content && | ||||||
|  | 	hg add content && | ||||||
|  | 	hg commit -m one | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 
 | ||||||
|  | 	(cd hgrepo && hg tag v1.0) && | ||||||
|  | 	(cd gitrepo && git pull) && | ||||||
|  | 
 | ||||||
|  | 	echo "v1.0" > expected && | ||||||
|  | 	git --git-dir=gitrepo/.git tag > actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'push merged named branch' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo one > content && | ||||||
|  | 	hg add content && | ||||||
|  | 	hg commit -m one && | ||||||
|  | 	hg branch feature && | ||||||
|  | 	echo two > content && | ||||||
|  | 	hg commit -m two && | ||||||
|  | 	hg update default && | ||||||
|  | 	echo three > content && | ||||||
|  | 	hg commit -m three | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	cd gitrepo && | ||||||
|  | 	git merge -m Merge -Xtheirs origin/branches/feature && | ||||||
|  | 	git push | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	cat > expected <<-EOF | ||||||
|  | 	Merge | ||||||
|  | 	three | ||||||
|  | 	two | ||||||
|  | 	one | ||||||
|  | 	EOF | ||||||
|  | 	hg -R hgrepo log --template "{desc}\n" > actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'light tag sets author' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo one > content && | ||||||
|  | 	hg add content && | ||||||
|  | 	hg commit -m one | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	cd gitrepo && | ||||||
|  | 	git tag v1.0 && | ||||||
|  | 	git push --tags | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	echo "C O Mitter <committer@example.com>" > expected && | ||||||
|  | 	hg -R hgrepo log --template "{author}\n" -r tip > actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'push tag different branch' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 	echo one > content && | ||||||
|  | 	hg add content && | ||||||
|  | 	hg commit -m one | ||||||
|  | 	hg branch feature && | ||||||
|  | 	echo two > content && | ||||||
|  | 	hg commit -m two | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	cd gitrepo && | ||||||
|  | 	git branch && | ||||||
|  | 	git checkout branches/feature && | ||||||
|  | 	git tag v1.0 && | ||||||
|  | 	git push --tags | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	echo feature > expected && | ||||||
|  | 	hg -R hgrepo log --template="{branch}\n" -r tip > actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'cloning a removed file works' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 
 | ||||||
|  | 	echo test > test_file && | ||||||
|  | 	hg add test_file && | ||||||
|  | 	hg commit -m add && | ||||||
|  | 
 | ||||||
|  | 	hg rm test_file && | ||||||
|  | 	hg commit -m remove | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	check_files gitrepo | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'cloning a file replaced with a directory' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 
 | ||||||
|  | 	echo test > dir_or_file && | ||||||
|  | 	hg add dir_or_file && | ||||||
|  | 	hg commit -m add && | ||||||
|  | 
 | ||||||
|  | 	hg rm dir_or_file && | ||||||
|  | 	mkdir dir_or_file && | ||||||
|  | 	echo test > dir_or_file/test_file && | ||||||
|  | 	hg add dir_or_file/test_file && | ||||||
|  | 	hg commit -m replase | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	check_files gitrepo "dir_or_file/test_file" | ||||||
|  | ' | ||||||
|  | 
 | ||||||
|  | test_expect_success 'clone replace directory with a file' ' | ||||||
|  | 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||||
|  | 
 | ||||||
|  | 	( | ||||||
|  | 	hg init hgrepo && | ||||||
|  | 	cd hgrepo && | ||||||
|  | 
 | ||||||
|  | 	mkdir dir_or_file && | ||||||
|  | 	echo test > dir_or_file/test_file && | ||||||
|  | 	hg add dir_or_file/test_file && | ||||||
|  | 	hg commit -m add && | ||||||
|  | 
 | ||||||
|  | 	hg rm dir_or_file/test_file && | ||||||
|  | 	echo test > dir_or_file && | ||||||
|  | 	hg add dir_or_file && | ||||||
|  | 	hg commit -m add && | ||||||
|  | 
 | ||||||
|  | 	hg rm dir_or_file | ||||||
|  | 	) && | ||||||
|  | 
 | ||||||
|  | 	git clone "hg::hgrepo" gitrepo && | ||||||
|  | 	check_files gitrepo "dir_or_file" | ||||||
|  | ' | ||||||
|  | 
 | ||||||
| test_done | test_done | ||||||
		Reference in New Issue
	
	Block a user