mirror of
				https://github.com/mnauw/git-remote-hg.git
				synced 2025-10-31 08:35:48 +01:00 
			
		
		
		
	Compare commits
	
		
			172 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 88b2756e43 | ||
|  | d000a0b5e6 | ||
|  | 4e119d9ea6 | ||
|  | e31f83cbc5 | ||
|  | 5e1aa3a8e0 | ||
|  | ce7ddae09a | ||
|  | bad0a3e5e5 | ||
|  | 705f9ecaec | ||
|  | 7c3eccdb93 | ||
|  | 44d09e7d37 | ||
|  | f87d0bc1a1 | ||
|  | 54804bc402 | ||
|  | 99c02f49df | ||
|  | 39960e1ae8 | ||
|  | 5353a87001 | ||
|  | 9a80e68234 | ||
|  | f4cdd20cb1 | ||
|  | 16b33919e4 | ||
|  | 9813797360 | ||
|  | e1a9c3e91b | ||
|  | a8f6d92613 | ||
|  | 4b8a307400 | ||
|  | 6d75435eab | ||
|  | d47a4abdae | ||
|  | afdb8943ea | ||
|  | dc1be060d1 | ||
|  | 13781788eb | ||
|  | 5061e6a322 | ||
|  | 587099b968 | ||
|  | b5f104364f | ||
|  | a48d4fd7fb | ||
|  | 301552278a | ||
|  | fddbbfe990 | ||
|  | c329c9690a | ||
|  | 6c36268028 | ||
|  | 893dd9434f | ||
|  | 4ddbfeb9c8 | ||
|  | 93271a4e1b | ||
|  | 36706dffe6 | ||
|  | da532bf6f4 | ||
|  | aa1d0bc152 | ||
|  | bdbe62256a | ||
|  | 8acf139e44 | ||
|  | 1df692295c | ||
|  | 027e1a16f0 | ||
|  | 723e6c76fc | ||
|  | 2529c986c2 | ||
|  | ab398ade1d | ||
|  | e1d25cf97c | ||
|  | 0fe1e359ec | ||
|  | 498c615051 | ||
|  | 6b6aa9deaa | ||
|  | 2685f56c7c | ||
|  | 3314ce3dda | ||
|  | 408333afca | ||
|  | c861db6add | ||
|  | d2a3a646af | ||
|  | f00911668a | ||
|  | 474cacd81d | ||
|  | e4d87d5e2c | ||
|  | 615cc7fe04 | ||
|  | 79e75991ab | ||
|  | b029ac0500 | ||
|  | 7713b7ecef | ||
|  | b274b8057e | ||
|  | 451e31022a | ||
|  | 9c61c09ebf | ||
|  | 463f397ba4 | ||
|  | e774ad2d96 | ||
|  | 086ca23507 | ||
|  | 7c373be665 | ||
|  | 3bfec5fc6f | ||
|  | 7908c70efb | ||
|  | 7cff2c6adb | ||
|  | 9c5b8835f4 | ||
|  | 537e5a4735 | ||
|  | 8025945a62 | ||
|  | 33dccdfab0 | ||
|  | 4ad9c8d70c | ||
|  | 740c681c1d | ||
|  | 995179444c | ||
|  | e6c479c136 | ||
|  | b8b9a2f571 | ||
|  | 4c50223dba | ||
|  | 35d32d5a75 | ||
|  | 7f6a843f0d | ||
|  | 63cf2780ba | ||
|  | f032d3617b | ||
|  | 60a1d7ae7a | ||
|  | 10aec96d88 | ||
|  | 9b54c626bc | ||
|  | d51f508916 | ||
|  | 9916fead46 | ||
|  | 09c4726083 | ||
|  | bb663c032f | ||
|  | b590aec106 | ||
|  | 4496af4a5c | ||
|  | 890080673b | ||
|  | 5e6ef0a1d5 | ||
|  | a1e2c4acc9 | ||
|  | 7196dac02d | ||
|  | a8bb2a28a3 | ||
|  | ffcb41cc52 | ||
|  | 9949745533 | ||
|  | 83620648ab | ||
|  | 30a2d61bdf | ||
|  | 2fdb786fc4 | ||
|  | 79797918ff | ||
|  | d45d5cde50 | ||
|  | 7078666c77 | ||
|  | 08e453f8db | ||
|  | ec7119d0ef | ||
|  | 6ae5e3961e | ||
|  | b4c3277f72 | ||
|  | de9bf35388 | ||
|  | 857d68708b | ||
|  | 7394fc890e | ||
|  | 22229dd738 | ||
|  | 5cd03ad0fd | ||
|  | bf7ad934d7 | ||
|  | 426ed618b2 | ||
|  | 5f34d049b9 | ||
|  | ea7e9bf31a | ||
|  | a3a36883c5 | ||
|  | 0fdd28319a | ||
|  | a5bc03d4d6 | ||
|  | 104e8895d6 | ||
|  | 30f31c13ce | ||
|  | 485806e1e3 | ||
|  | 6e13c1c818 | ||
|  | ce38d52ce5 | ||
|  | 6b8ee2f1b6 | ||
|  | b3b9b5de39 | ||
|  | 34ba087896 | ||
|  | 4aec2fe3cc | ||
|  | e892cb6ce3 | ||
|  | 59ad50c6d0 | ||
|  | b8c8b1fd00 | ||
|  | 0cf8b2c20a | ||
|  | 8c3cde6be7 | ||
|  | ccee8909ff | ||
|  | dd6b72df21 | ||
|  | 01d619ad3c | ||
|  | 9d45e70fce | ||
|  | 055cec1aa7 | ||
|  | 7d50fa42c1 | ||
|  | f6676e6d86 | ||
|  | cac075744d | ||
|  | 19633eaf36 | ||
|  | 900a55e974 | ||
|  | d1f60c445e | ||
|  | bd3f404d34 | ||
|  | dcf96f31db | ||
|  | 795b88e16c | ||
|  | 20366b4b20 | ||
|  | 1f5134062e | ||
|  | 2313dc2ca0 | ||
|  | 0e52a6c883 | ||
|  | e24a713dc9 | ||
|  | 122b7f5da2 | ||
|  | 98c1c9263e | ||
|  | 85293dcf69 | ||
|  | 970883c46c | ||
|  | ad77f125b7 | ||
|  | 5dcd6df3c8 | ||
|  | ed80437db4 | ||
|  | 0a1e8ecbc7 | ||
|  | 6d6504d1fd | ||
|  | 237ff083af | ||
|  | 0c8f8571c7 | ||
|  | 1442c29d39 | ||
|  | dfa3ad5fca | 
							
								
								
									
										44
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| name: CI | ||||
|  | ||||
| # on: [push] | ||||
| on: | ||||
|   # save cycles; disable on push, enable manual trigger | ||||
|   workflow_dispatch: | ||||
|  | ||||
| jobs: | ||||
|   test: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       matrix: | ||||
|         hg: [ '6.0', '6.1', '6.2', '6.3', '6.4', '6.5', '6.6', '6.7', '6.8', '6.9', '7.0' ] | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: '3.11' | ||||
|       - uses: actions/cache@v4 | ||||
|         id: cache-pip | ||||
|         with: | ||||
|           path: ~/.cache/pip | ||||
|           key: pip | ||||
|       - name: Install hg | ||||
|         run: | ||||
|           pip install mercurial==${{ matrix.hg }} | ||||
|       - run: prove -j4 | ||||
|   test-windows: | ||||
|     runs-on: windows-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: actions/setup-python@v5 | ||||
|         with: | ||||
|           python-version: '3.11' | ||||
|       - uses: actions/cache@v4 | ||||
|         id: cache-pip | ||||
|         with: | ||||
|           path: ~/appdata/local/pip/cache | ||||
|           key: pip-windows | ||||
|       - name: Install hg | ||||
|         run: | ||||
|           pip install mercurial | ||||
|       - name: Run all tests | ||||
|         run: prove -j4 --exec bash.exe | ||||
							
								
								
									
										20
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,20 +0,0 @@ | ||||
| dist: xenial | ||||
| language: minimal | ||||
|  | ||||
| cache: | ||||
|   directories: | ||||
|     - $HOME/.cache/git-remote-hg | ||||
|  | ||||
| script: | ||||
|   - ./tools/check-versions hg:$HG_VERSION | ||||
|  | ||||
| matrix: | ||||
|   include: | ||||
|     - env: | ||||
|     - env: HG_VERSION=@ | ||||
|     - env: HG_VERSION=5.0 | ||||
|     - env: HG_VERSION=4.9 | ||||
|     - env: HG_VERSION=4.8 | ||||
|     - env: HG_VERSION=4.7 | ||||
|     - env: HG_VERSION=4.6 | ||||
|     - env: HG_VERSION=4.5 | ||||
							
								
								
									
										4
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
									
									
									
									
								
							| @@ -29,10 +29,10 @@ build: | ||||
| doc: doc/git-remote-hg.1 | ||||
|  | ||||
| test: | ||||
| 	$(MAKE) -C test | ||||
| 	$(MAKE) -C t | ||||
|  | ||||
| doc/git-remote-hg.1: doc/git-remote-hg.txt | ||||
| 	a2x -d manpage -f manpage $< | ||||
| 	asciidoctor -d manpage -b manpage $< | ||||
|  | ||||
| clean: | ||||
| 	$(RM) doc/git-remote-hg.1 | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| 'git-remote-hg' is the semi-official Mercurial bridge from Git project, once | ||||
| `git-remote-hg` is the semi-official Mercurial bridge from the Git project, once | ||||
| installed, it allows you to clone, fetch and push to and from Mercurial | ||||
| repositories as if they were Git ones: | ||||
|  | ||||
| @@ -6,10 +6,10 @@ 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`: | ||||
| To enable this, simply add the `git-remote-hg` script anywhere in your `$PATH`: | ||||
|  | ||||
| -------------------------------------- | ||||
| wget https://raw.github.com/mnauw/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg | ||||
| wget https://raw.githubusercontent.com/mnauw/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg | ||||
| chmod +x ~/bin/git-remote-hg | ||||
| -------------------------------------- | ||||
|  | ||||
| @@ -49,7 +49,8 @@ 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): | ||||
| If you are not interested in Mercurial permanent and global branches (aka. | ||||
| commit labels): | ||||
|  | ||||
| -------------------------------------- | ||||
| % git config --global remote-hg.track-branches false | ||||
| @@ -57,29 +58,47 @@ If you are not interested in Mercurial permanent and global branches (aka. commi | ||||
|  | ||||
| With this configuration, the 'branches/foo' refs won't appear. | ||||
|  | ||||
| If you want the equivalent of 'hg clone --insecure': | ||||
| 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: | ||||
| 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 | ||||
| -------------------------------------- | ||||
|  | ||||
| **** | ||||
| mnauw's note; The above is not quite the case, it only ever has been (somewhat) | ||||
| if an undocumented debug mode (`debugextrainmessage` setting) was enabled | ||||
| in (likely somewhat patched) `hg-git`.  And as of `hg-git` v1.2.0 the latter is | ||||
| no longer considered.  In fact, `hg-git` creates git commits with additional hg | ||||
| metadata stored in so-called "extra commit headers". The latter might be seen by | ||||
| `git log --format=raw` or `git cat-file -p <commitid>`, but are otherwise mostly | ||||
| only used internally by the git suite (for signatures).  While they are supported | ||||
| by `dulwich`'s API (which is a python git implementation), there is, however, | ||||
| limited to no support for those in git "porcelain or plumbing" commands. In | ||||
| particular, `git fast-export` and `git fast-import` do not consider these, so a | ||||
| `gitremote-helpers` tool is then also out of luck.  Incidentally, it also | ||||
| follows that a `git fast-export | git fast-import` "clone" approach would also | ||||
| lose such extra metadata, and likewise so for e.g. `git filter-repo`. | ||||
|  | ||||
| All in all, this mode is not quite recommended. | ||||
| If the concern here is not so much `hg-git` compatibility but rather "hg-git-hg | ||||
| round-trip fidelity", then see the discussion below on `check-hg-commits` setting. | ||||
| **** | ||||
|  | ||||
| == Notes == | ||||
|  | ||||
| Remember to run `git gc --aggressive` after cloning a repository, specially if | ||||
| Remember to run `git gc --aggressive` after cloning a repository, especially 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: | ||||
| To push a branch, you need to use the 'branches/' prefix: | ||||
|  | ||||
| -------------------------------------- | ||||
| % git checkout branches/next | ||||
| @@ -89,7 +108,7 @@ To push a branch, you need to use the "branches/" prefix: | ||||
|  | ||||
| All the pushed commits will receive the "next" Mercurial named branch. | ||||
|  | ||||
| *Note*: Make sure you don't have +remote-hg.track-branches+ disabled. | ||||
| *Note*: Make sure you don't have `remote-hg.track-branches` disabled. | ||||
|  | ||||
| === Cloning HTTPS === | ||||
|  | ||||
| @@ -99,7 +118,7 @@ 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]: | ||||
| You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]: | ||||
|  | ||||
| -------------------------------------- | ||||
| [auth] | ||||
| @@ -109,11 +128,7 @@ 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. | ||||
| https://pypi.org/project/mercurial_keyring[keyring extension]. | ||||
|  | ||||
| === Submodules === | ||||
|  | ||||
| @@ -141,10 +156,10 @@ 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 | ||||
| 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 | ||||
| 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]). | ||||
|  | ||||
| @@ -170,16 +185,27 @@ below for more details. | ||||
|  | ||||
| == 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 | ||||
| (_though actually no longer so nowadays_): | ||||
| There are other `git-remote-hg` projects out there, but this is the original, | ||||
| which was distributed officially in 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] | ||||
| Over the years many similar tools have died out, the only actively maintained | ||||
| alternative is mnauw's fork of this project: | ||||
| https://github.com/mnauw/git-remote-hg[mnauw/git-remote-hg]. I've merged some of | ||||
| his patches, and he has merged some of my patches, so the projects are mostly in | ||||
| sync, but not quite. In particular Nauwelaerts' fork has many administrative | ||||
| extensions, which although useful to some people, I don't believe they belong | ||||
| in the core. | ||||
|  | ||||
| For a comparison between these and other projects go | ||||
| https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives[here]. | ||||
|  | ||||
| **** | ||||
| mnauw's note; I do not know what "the core" means? | ||||
| However, the "extensions" provide useful and possibly | ||||
| critical maintenance wrt git-remote-hg's internal data, so it belongs as close | ||||
| to the latter one as possible. | ||||
| **** | ||||
|  | ||||
| [[no-limitations]] | ||||
| == Limitations (or not) == | ||||
|  | ||||
| @@ -361,7 +387,8 @@ up elsewhere as expected (regardless of conversion mapping or ABI). | ||||
|  | ||||
| Note that identifying and re-using the hg changeset relies on metadata | ||||
| (`refs/notes/hg` and marks files) that is not managed or maintained by any | ||||
| git-to-git fetch (or clone). | ||||
| git-to-git fetch (or clone) (as that is only automatically so for `refs/heads/`, | ||||
| though it could be pushed manually). | ||||
| As such (and as said), this approach aims for plain-and-simple safety, but only | ||||
| within a local scope (git repo). | ||||
|  | ||||
|   | ||||
| @@ -38,7 +38,8 @@ 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): | ||||
| If you are not interested in Mercurial permanent and global branches (aka. | ||||
| commit labels): | ||||
|  | ||||
| -------------------------------------- | ||||
| % git config --global remote-hg.track-branches false | ||||
| @@ -52,7 +53,8 @@ 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: | ||||
| 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 | ||||
| @@ -102,19 +104,32 @@ the invalid '~' | ||||
| % git config --global remote-hg.ignore-name ~ | ||||
| -------------------------------------- | ||||
|  | ||||
| Even though the "gitdir" is configurable (using `GIT_DIR`), git does not accept | ||||
| certain pathname components, e.g. `.git` or `.gitmodules` (case-insensitive). | ||||
| Problems arise if the hg repo contains such pathnames, and recent git versions | ||||
| will reject this in a very hard way.  So these pathnames are now mapped | ||||
| from "hg space" to "git space" in a one-to-one way, where (e.g.) | ||||
| `.git[0 or more suffix]` is mapped to `.git[1 or more suffix]` (obviously by | ||||
| appending or removing a suffix). The "suffix" in question defaults to `_`, | ||||
| but can be configured using | ||||
|  | ||||
| -------------------------------------- | ||||
| % git config --global remote-hg.dotfile-suffix _ | ||||
| -------------------------------------- | ||||
|  | ||||
|  | ||||
| NOTES | ||||
| ----- | ||||
|  | ||||
| Remember to run `git gc --aggressive` after cloning a repository, specially if | ||||
| Remember to run `git gc --aggressive` after cloning a repository, especially 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. | ||||
| The newest supported version of Mercurial is 6.2, the oldest one is 2.4. | ||||
|  | ||||
| Pushing branches | ||||
| ~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| To push a Mercurial named branch, you need to use the "branches/" prefix: | ||||
| To push a branch, you need to use the "branches/" prefix: | ||||
|  | ||||
| -------------------------------------- | ||||
| % git checkout branches/next | ||||
| @@ -135,7 +150,7 @@ 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]: | ||||
| You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]: | ||||
|  | ||||
| -------------------------------------- | ||||
| [auth] | ||||
| @@ -145,7 +160,7 @@ bb.password = password | ||||
| -------------------------------------- | ||||
|  | ||||
| Finally, you can also use the | ||||
| https://pypi.python.org/pypi/mercurial_keyring[keyring extension]. | ||||
| https://pypi.org/project/mercurial_keyring[keyring extension]. | ||||
|  | ||||
| CAVEATS | ||||
| ------- | ||||
| @@ -157,10 +172,10 @@ 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 | ||||
| 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 | ||||
| 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]). | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,11 @@ | ||||
|  | ||||
| from mercurial import hg, ui, commands, util | ||||
| from mercurial import context, subrepo | ||||
| try: | ||||
|     # hg >= 5.8 | ||||
|     from mercurial.utils import urlutil | ||||
| except ImportError: | ||||
|     from mercurial import util as urlutil | ||||
|  | ||||
| import re | ||||
| import sys | ||||
| @@ -51,7 +56,13 @@ if sys.version_info[0] == 3: | ||||
|         stdout = sys.stdout.buffer | ||||
|         stderr = sys.stderr.buffer | ||||
|         getcwd = os.getcwdb | ||||
|         getenv = os.getenvb if os.supports_bytes_environ else os.getenv | ||||
|         @staticmethod | ||||
|         def getenvb(val, default): | ||||
|             result = os.getenv(val.decode(), default.decode() if hasattr(default, 'decode') else default) | ||||
|              # if result is a string, get bytes instead | ||||
|             result = result.encode() if hasattr(result, 'encode') else result | ||||
|             return result | ||||
|         getenv = os.getenvb if os.supports_bytes_environ else getenvb | ||||
| else: | ||||
|     class compat(basecompat): | ||||
|         # life was simple in those days ... | ||||
| @@ -86,11 +97,27 @@ def debug(msg, *args): | ||||
| def log(msg, *args): | ||||
|     logger.log(logging.LOG, msg, *args) | ||||
|  | ||||
| # new style way to import a source file | ||||
| def _imp_load_source(module_name, file_path): | ||||
|     import importlib.util | ||||
|     loader = importlib.machinery.SourceFileLoader(module_name, file_path) | ||||
|     spec = importlib.util.spec_from_loader(module_name, loader) | ||||
|     module = importlib.util.module_from_spec(spec) | ||||
|     sys.modules[module_name] = module | ||||
|     spec.loader.exec_module(module) | ||||
|     return module | ||||
|  | ||||
| def import_sibling(mod, filename): | ||||
|     import imp | ||||
|     mydir = os.path.dirname(__file__) | ||||
|     sys.dont_write_bytecode = True | ||||
|     return imp.load_source(mod, os.path.join(mydir, filename)) | ||||
|     vi = sys.version_info | ||||
|     ff = os.path.join(mydir, filename) | ||||
|     if vi.major >= 3 and vi.minor >= 5: | ||||
|         return _imp_load_source(mod, ff) | ||||
|     else: | ||||
|         import imp | ||||
|         return imp.load_source(mod, ff) | ||||
|  | ||||
|  | ||||
| class GitHgRepo: | ||||
|  | ||||
| @@ -135,7 +162,7 @@ class GitHgRepo: | ||||
|         process = self.start_cmd(args, **kwargs) | ||||
|         output = process.communicate()[0] | ||||
|         if check and process.returncode != 0: | ||||
|             die(b'command failed: %s' % b' '.join([compat.to_b(a) for a in cmd])) | ||||
|             die(b'git command failed: %s' % b' '.join([compat.to_b(a) for a in args])) | ||||
|         return output | ||||
|  | ||||
|     def get_config(self, config, getall=False): | ||||
| @@ -216,9 +243,12 @@ class GitHgRepo: | ||||
|                         warn(b'failed to find local hg for remote %s' % (r)) | ||||
|                         continue | ||||
|                 else: | ||||
|                     npath = os.path.abspath(hg_path) | ||||
|                     # use relative path if possible | ||||
|                     if check_version(4, 2): | ||||
|                         npath = os.path.join(b'..', b'..', b'..', b'.hg') | ||||
|                     # make sure the shared path is always up-to-date | ||||
|                     util.writefile(os.path.join(local_hg, b'sharedpath'), | ||||
|                         os.path.abspath(hg_path)) | ||||
|                     util.writefile(os.path.join(local_hg, b'sharedpath'), npath) | ||||
|                 self.hg_repos[r] = os.path.join(local_path) | ||||
|  | ||||
|         log('%s determined hg_repos %s', self.identity(), self.hg_repos) | ||||
| @@ -308,11 +338,11 @@ class GitHgRepo: | ||||
|             if not kind in (b'hg', b'git'): | ||||
|                 warn('skipping unsupported subrepo type %s' % kind) | ||||
|                 continue | ||||
|             if not util.url(src).isabs(): | ||||
|             if not urlutil.url(src).isabs(): | ||||
|                 parent = self.get_hg_repo_url(remote) | ||||
|                 if not parent: | ||||
|                     die(b'could not determine repo url of %s' % remote) | ||||
|                 parent = util.url(parent) | ||||
|                 parent = urlutil.url(parent) | ||||
|                 parent.path = posixpath.join(parent.path or b'', src) | ||||
|                 parent.path = posixpath.normpath(parent.path) | ||||
|                 src = bytes(parent) | ||||
| @@ -544,6 +574,43 @@ class GcCommand(SubCommand): | ||||
|                 gm.store() | ||||
|  | ||||
|  | ||||
| class MapFileCommand(SubCommand): | ||||
|  | ||||
|     def argumentparser(self): | ||||
|         usage = '%%(prog)s %s [options] <remote>' % (self.subcommand) | ||||
|         p = argparse.ArgumentParser(usage=usage) | ||||
|         p.add_argument('--output', required=True, | ||||
|             help='mapfile to write') | ||||
|         p.epilog = textwrap.dedent("""\ | ||||
|         Writes a so-called git-mapfile, as used internally by hg-git. | ||||
|         This files consists of lines of format `<githexsha> <hghexsha>`. | ||||
|  | ||||
|         As such, the result could be used to coax hg-git in some manner. | ||||
|         However, as git-remote-hg and hg-git may (likely) produce different | ||||
|         commits (either git or hg), mixed use of both tools is not recommended. | ||||
|         """) | ||||
|         return p | ||||
|  | ||||
|     def do(self, options, args): | ||||
|         remotehg = import_sibling('remotehg', 'git-remote-hg') | ||||
|  | ||||
|         if not args or len(args) != 1: | ||||
|             self.usage('expect 1 remote') | ||||
|  | ||||
|         remote = args[0] | ||||
|         hgpath = remotehg.select_marks_dir(remote, self.githgrepo.gitdir, False) | ||||
|         puts(b"Loading hg marks ...") | ||||
|         hgm = remotehg.Marks(os.path.join(hgpath, b'marks-hg'), None) | ||||
|         puts(b"Loading git marks ...") | ||||
|         gm = GitMarks(os.path.join(hgpath, b'marks-git')) | ||||
|         puts(b"Writing mapfile ...") | ||||
|         with open(options.output, 'wb') as f: | ||||
|             for c, m in gm.marks.items(): | ||||
|                 hgc = hgm.rev_marks.get(m, None) | ||||
|                 if hgc: | ||||
|                     f.write(b'%s %s\n' % (c, hgc)) | ||||
|  | ||||
|  | ||||
| class SubRepoCommand(SubCommand): | ||||
|  | ||||
|     def writestate(repo, state): | ||||
| @@ -910,6 +977,7 @@ def get_subcommands(): | ||||
|         b'repo': RepoCommand, | ||||
|         b'gc':  GcCommand, | ||||
|         b'sub': SubRepoCommand, | ||||
|         b'mapfile': MapFileCommand, | ||||
|         b'help' : HelpCommand | ||||
|     } | ||||
|     # add remote named subcommands | ||||
| @@ -932,6 +1000,7 @@ def do_usage(): | ||||
|     gc      \t perform maintenance and consistency cleanup on repo tracking marks | ||||
|     sub     \t manage subrepos | ||||
|     repo    \t show local hg repo backing a remote | ||||
|     mapfile \t dump a hg-git git-mapfile | ||||
|  | ||||
|     If the subcommand is the name of a remote hg repo, then any remaining arguments | ||||
|     are considered a "hg command", e.g. hg heads, or thg, and it is then executed | ||||
|   | ||||
							
								
								
									
										256
									
								
								git-remote-hg
									
									
									
									
									
								
							
							
						
						
									
										256
									
								
								git-remote-hg
									
									
									
									
									
								
							| @@ -86,7 +86,13 @@ if sys.version_info[0] == 3: | ||||
|         stdout = sys.stdout.buffer | ||||
|         stderr = sys.stderr.buffer | ||||
|         getcwd = os.getcwdb | ||||
|         getenv = os.getenvb if os.supports_bytes_environ else os.getenv | ||||
|         @staticmethod | ||||
|         def getenvb(val, default): | ||||
|             result = os.getenv(val.decode(), default.decode() if hasattr(default, 'decode') else default) | ||||
|              # if result is a string, get bytes instead | ||||
|             result = result.encode() if hasattr(result, 'encode') else result | ||||
|             return result | ||||
|         getenv = os.getenvb if os.supports_bytes_environ else getenvb | ||||
|         urlparse = urllib.parse.urlparse | ||||
|         urljoin = urllib.parse.urljoin | ||||
| else: | ||||
| @@ -116,6 +122,27 @@ else: | ||||
|         urlparse = staticmethod(_urlparse) | ||||
|         urljoin = staticmethod(_urljoin) | ||||
|  | ||||
| # new style way to import a source file | ||||
| def _imp_load_source(module_name, file_path): | ||||
|     import importlib.util | ||||
|     loader = importlib.machinery.SourceFileLoader(module_name, file_path) | ||||
|     spec = importlib.util.spec_from_loader(module_name, loader) | ||||
|     module = importlib.util.module_from_spec(spec) | ||||
|     sys.modules[module_name] = module | ||||
|     spec.loader.exec_module(module) | ||||
|     return module | ||||
|  | ||||
| def import_sibling(mod, filename): | ||||
|     mydir = os.path.dirname(__file__) | ||||
|     sys.dont_write_bytecode = True | ||||
|     vi = sys.version_info | ||||
|     ff = os.path.join(mydir, filename) | ||||
|     if vi.major >= 3 and vi.minor >= 5: | ||||
|         return _imp_load_source(mod, ff) | ||||
|     else: | ||||
|         import imp | ||||
|         return imp.load_source(mod, ff) | ||||
|  | ||||
| # | ||||
| # If you want to see Mercurial revisions as Git commit notes: | ||||
| # git config core.notesRef refs/notes/hg | ||||
| @@ -141,11 +168,11 @@ else: | ||||
| # Commits are modified to preserve hg information and allow bidirectionality. | ||||
| # | ||||
|  | ||||
| NAME_RE = re.compile(b'^([^<>]+)') | ||||
| AUTHOR_RE = re.compile(b'^([^<>]+?)? ?[<>]([^<>]*)(?:$|>)') | ||||
| NAME_RE = re.compile(br'^([^<>]+)') | ||||
| AUTHOR_RE = re.compile(br'^([^<>]+?)? ?[<>]([^<>]*)(?:$|>)') | ||||
| EMAIL_RE = re.compile(br'([^ \t<>]+@[^ \t<>]+)') | ||||
| AUTHOR_HG_RE = re.compile(b'^(.*?) ?<(.*?)(?:>(.*))?$') | ||||
| RAW_AUTHOR_RE = re.compile(b'^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)') | ||||
| AUTHOR_HG_RE = re.compile(br'^(.*?) ?<(.*?)(?:>(.*))?$') | ||||
| RAW_AUTHOR_RE = re.compile(br'^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)') | ||||
|  | ||||
| VERSION = 2 | ||||
|  | ||||
| @@ -153,6 +180,9 @@ def die(msg): | ||||
|     compat.stderr.write(b'ERROR: %s\n' % compat.to_b(msg, 'utf-8')) | ||||
|     sys.exit(1) | ||||
|  | ||||
| def debug(*args): | ||||
|     compat.stderr.write(b'DEBUG: %s\n' % compat.to_b(repr(args))) | ||||
|  | ||||
| def warn(msg): | ||||
|     compat.stderr.write(b'WARNING: %s\n' % compat.to_b(msg, 'utf-8')) | ||||
|     compat.stderr.flush() | ||||
| @@ -231,27 +261,17 @@ def get_rev_hg(commit): | ||||
|  | ||||
| class Marks: | ||||
|  | ||||
|     def __init__(self, path, repo): | ||||
|     def __init__(self, path, _repo=None): | ||||
|         self.path = path | ||||
|         self.repo = repo | ||||
|         self.clear() | ||||
|         self.load() | ||||
|  | ||||
|         if self.version < VERSION: | ||||
|             if self.version == 1: | ||||
|                 self.upgrade_one() | ||||
|  | ||||
|             # upgraded? | ||||
|             if self.version < VERSION: | ||||
|                 self.clear() | ||||
|                 self.version = VERSION | ||||
|  | ||||
|     def clear(self): | ||||
|         self.tips = {} | ||||
|         self.marks = {} | ||||
|         self.rev_marks = {} | ||||
|         self.last_mark = 0 | ||||
|         self.version = 0 | ||||
|         self.version = VERSION | ||||
|         self.last_note = 0 | ||||
|  | ||||
|     def load(self): | ||||
| @@ -267,20 +287,12 @@ class Marks: | ||||
|         self.tips = [] | ||||
|         self.marks = marks | ||||
|         self.last_mark = tmp['last-mark'] | ||||
|         self.version = tmp.get('version', 1) | ||||
|         self.version = tmp['version'] | ||||
|         self.last_note = 0 | ||||
|  | ||||
|         for rev, mark in compat.iteritems(self.marks): | ||||
|             self.rev_marks[mark] = rev | ||||
|  | ||||
|     def upgrade_one(self): | ||||
|         def get_id(rev): | ||||
|             return hghex(self.repo.changelog.node(int(rev))) | ||||
|         self.tips = dict((name, get_id(rev)) for name, rev in compat.iteritems(self.tips)) | ||||
|         self.marks = dict((get_id(rev), mark) for rev, mark in compat.iteritems(self.marks)) | ||||
|         self.rev_marks = dict((mark, get_id(rev)) for mark, rev in compat.iteritems(self.rev_marks)) | ||||
|         self.version = 2 | ||||
|  | ||||
|     def dict(self): | ||||
|         return { 'tips': self.tips, 'marks': self.marks, | ||||
|                 'last-mark': self.last_mark, 'version': self.version, | ||||
| @@ -383,7 +395,7 @@ class Parser: | ||||
|             return None | ||||
|         _, name, email, date, tz = m.groups() | ||||
|         if name and b'ext:' in name: | ||||
|             m = re.match(b'^(.+?) ext:\((.+)\)$', name) | ||||
|             m = re.match(br'^(.+?) ext:\((.+)\)$', name) | ||||
|             if m: | ||||
|                 name = m.group(1) | ||||
|                 ex = compat.urlunquote(m.group(2)) | ||||
| @@ -402,40 +414,38 @@ class Parser: | ||||
|         return (user, int(date), hgtz(tz)) | ||||
|  | ||||
| def fix_file_path(path): | ||||
|     def posix_path(path): | ||||
|         if os.sep == '/': | ||||
|             return path | ||||
|         # even Git for Windows expects forward | ||||
|         return path.replace(compat.to_b(os.sep), b'/') | ||||
|     # also converts forward slash to backwards slash on Win | ||||
|     path = os.path.normpath(path) | ||||
|     if not os.path.isabs(path): | ||||
|         return posix_path(path) | ||||
|     return posix_path(os.path.relpath(path, b'/')) | ||||
|     if os.path.isabs(path): | ||||
|         path = os.path.relpath(path, b'/') | ||||
|     if os.sep == '/': | ||||
|         return path | ||||
|     # even Git for Windows expects forward | ||||
|     return path.replace(compat.to_b(os.sep), b'/') | ||||
|  | ||||
| def export_files(files): | ||||
|     final = [] | ||||
|     for f in files: | ||||
|         fid = node.hex(f.filenode()) | ||||
| def export_file(ctx, fname): | ||||
|     f = ctx.filectx(fname) | ||||
|     fid = node.hex(f.filenode()) | ||||
|  | ||||
|         if fid in filenodes: | ||||
|             mark = filenodes[fid] | ||||
|         else: | ||||
|             mark = marks.next_mark() | ||||
|             filenodes[fid] = mark | ||||
|             d = f.data() | ||||
|     if fid in filenodes: | ||||
|         mark = filenodes[fid] | ||||
|     else: | ||||
|         mark = marks.next_mark() | ||||
|         filenodes[fid] = mark | ||||
|         d = f.data() | ||||
|  | ||||
|             puts(b"blob") | ||||
|             puts(b"mark :%u" % mark) | ||||
|             puts(b"data %d" % len(d)) | ||||
|             puts(d) | ||||
|         puts(b"blob") | ||||
|         puts(b"mark :%u" % mark) | ||||
|         puts(b"data %d" % len(d)) | ||||
|         puts(f.data()) | ||||
|  | ||||
|         path = fix_file_path(f.path()) | ||||
|         final.append((gitmode(f.flags()), mark, path)) | ||||
|  | ||||
|     return final | ||||
|     path = fixup_path_to_git(fix_file_path(f.path())) | ||||
|     return (gitmode(f.flags()), mark, path) | ||||
|  | ||||
| def get_filechanges(repo, ctx, parent): | ||||
|     if hasattr(parent, 'status'): | ||||
|         stat = parent.status(ctx) | ||||
|         return stat.modified + stat.added, stat.removed | ||||
|  | ||||
|     modified = set() | ||||
|     added = set() | ||||
|     removed = set() | ||||
| @@ -477,7 +487,7 @@ def fixup_user_git(user): | ||||
| def fixup_user_hg(user): | ||||
|     def sanitize(name): | ||||
|         # stole this from hg-git | ||||
|         return re.sub(b'[<>\n]', b'?', name.lstrip(b'< ').rstrip(b'> ')) | ||||
|         return re.sub(br'[<>\n]', b'?', name.lstrip(b'< ').rstrip(b'> ')) | ||||
|  | ||||
|     m = AUTHOR_HG_RE.match(user) | ||||
|     if m: | ||||
| @@ -508,6 +518,51 @@ def fixup_user(user): | ||||
|  | ||||
|     return b'%s <%s>' % (name, mail) | ||||
|  | ||||
| # (recent) git fast-import does not accept .git or .gitmodule component names | ||||
| # (anywhere, case-insensitive) | ||||
| # in any case, surprising things may happen, so add some front-end replacement magic; | ||||
| # transform of (hg) .git(0 or more suffix) to (git) .git(1 or more suffix) | ||||
| # (likewise so for any invalid git keyword) | ||||
| def fixup_dotfile_path(path, suffix, add): | ||||
|     def subst(part): | ||||
|         if (not part) or part[0] != ord(b'.'): | ||||
|             return part | ||||
|         for prefix in (b'.git', b'.gitmodules'): | ||||
|             pl = len(prefix) | ||||
|             tail = len(part) - pl | ||||
|             if tail < 0: | ||||
|                 continue | ||||
|             if part[0:pl].lower() == prefix and part[pl:] == suffix * tail: | ||||
|                 if add: | ||||
|                     return part + suffix | ||||
|                 elif tail == 0: | ||||
|                     # .git should not occur in git space | ||||
|                     # so complain | ||||
|                     if pl == 3: | ||||
|                         die('invalid path component %s' % part) | ||||
|                     else: | ||||
|                         # but .gitmodules might | ||||
|                         # leave as-is, it is handled/ignored elsewhere | ||||
|                         return part | ||||
|                 else: | ||||
|                     return part[0:-1] | ||||
|         return part | ||||
|     # quick optimization check; | ||||
|     if (not path) or (path[0] != ord(b'.') and path.find(b'/.') < 0): | ||||
|         return path | ||||
|     sep = b'/' | ||||
|     return sep.join((subst(part) for part in path.split(sep))) | ||||
|  | ||||
| def fixup_path_to_git(path): | ||||
|     if not dotfile_suffix: | ||||
|         return path | ||||
|     return fixup_dotfile_path(path, dotfile_suffix, True) | ||||
|  | ||||
| def fixup_path_from_git(path): | ||||
|     if not dotfile_suffix: | ||||
|         return path | ||||
|     return fixup_dotfile_path(path, dotfile_suffix, False) | ||||
|  | ||||
| def updatebookmarks(repo, peer): | ||||
|     remotemarks = peer.listkeys(b'bookmarks') | ||||
|  | ||||
| @@ -579,18 +634,6 @@ def get_repo(url, alias): | ||||
|     else: | ||||
|         shared_path = os.path.join(gitdir, b'hg') | ||||
|  | ||||
|         # check and upgrade old organization | ||||
|         hg_path = os.path.join(shared_path, b'.hg') | ||||
|         if os.path.exists(shared_path) and not os.path.exists(hg_path): | ||||
|             repos = os.listdir(shared_path) | ||||
|             for x in repos: | ||||
|                 local_hg = os.path.join(shared_path, x, b'clone', b'.hg') | ||||
|                 if not os.path.exists(local_hg): | ||||
|                     continue | ||||
|                 if not os.path.exists(hg_path): | ||||
|                     shutil.move(local_hg, hg_path) | ||||
|                 shutil.rmtree(os.path.join(shared_path, x, b'clone')) | ||||
|  | ||||
|         # setup shared repo (if not there) | ||||
|         try: | ||||
|             hg.peer(myui, {}, shared_path, create=True) | ||||
| @@ -601,8 +644,13 @@ def get_repo(url, alias): | ||||
|             os.makedirs(dirname) | ||||
|  | ||||
|         local_path = os.path.join(dirname, b'clone') | ||||
|         kwargs = {} | ||||
|         hg_path = os.path.join(shared_path, b'.hg') | ||||
|         if check_version(4, 2): | ||||
|             kwargs = {'relative': True} | ||||
|             hg_path = os.path.join(b'..', b'..', b'..', b'.hg') | ||||
|         if not os.path.exists(local_path): | ||||
|             hg.share(myui, shared_path, local_path, update=False) | ||||
|             hg.share(myui, shared_path, local_path, update=False, **kwargs) | ||||
|         else: | ||||
|             # make sure the shared path is always up-to-date | ||||
|             util.writefile(os.path.join(local_path, b'.hg', b'sharedpath'), hg_path) | ||||
| @@ -711,11 +759,16 @@ def export_ref(repo, name, kind, head): | ||||
|                 if rename: | ||||
|                     renames.append((rename[0], f)) | ||||
|  | ||||
|             # NOTE no longer used in hg-git, a HG:rename extra header is used | ||||
|             for e in renames: | ||||
|                 extra_msg += b"rename : %s => %s\n" % e | ||||
|  | ||||
|             for key, value in compat.iteritems(extra): | ||||
|                 if key in (b'author', b'committer', b'encoding', b'message', b'branch', b'hg-git'): | ||||
|                 if key in (b'author', b'committer', b'encoding', b'message', b'branch', b'hg-git', b'transplant_source'): | ||||
|                     continue | ||||
|                 elif key == b'hg-git-rename-source' and value == b'git': | ||||
|                     # extra data that hg-git might put there unconditionally | ||||
|                     # or that we put in there to be compatible | ||||
|                     continue | ||||
|                 else: | ||||
|                     extra_msg += b"extra : %s : %s\n" % (key, compat.urlquote(value)) | ||||
| @@ -726,7 +779,7 @@ def export_ref(repo, name, kind, head): | ||||
|         if len(parents) == 0: | ||||
|             puts(b'reset %s/%s' % (prefix, ename)) | ||||
|  | ||||
|         modified_final = export_files(c.filectx(f) for f in modified) | ||||
|         modified_final = [export_file(c, fname) for fname in modified] | ||||
|  | ||||
|         puts(b"commit %s/%s" % (prefix, ename)) | ||||
|         puts(b"mark :%d" % (marks.get_mark(c.hex()))) | ||||
| @@ -741,7 +794,7 @@ def export_ref(repo, name, kind, head): | ||||
|                 puts(b"merge :%u" % (rev_to_mark(parents[1]))) | ||||
|  | ||||
|         for f in removed: | ||||
|             puts(b"D %s" % (fix_file_path(f))) | ||||
|             puts(b"D %s" % fixup_path_to_git(fix_file_path(f))) | ||||
|         for f in modified_final: | ||||
|             puts(b"M %s :%u %s" % f) | ||||
|         puts() | ||||
| @@ -839,8 +892,11 @@ def do_list(parser, branchmap): | ||||
|  | ||||
|     for branch, heads in compat.iteritems(branchmap): | ||||
|         # only open heads | ||||
|         heads = [h for h in heads if b'close' not in repo.changelog.read(h)[5]] | ||||
|         if heads: | ||||
|         try: | ||||
|             heads = [h for h in heads if b'close' not in repo.changelog.read(h)[5]] | ||||
|             if heads: | ||||
|                 branches[branch] = heads | ||||
|         except error.LookupError: | ||||
|             branches[branch] = heads | ||||
|  | ||||
|     list_head(repo, cur) | ||||
| @@ -1031,6 +1087,7 @@ def parse_commit(parser): | ||||
|         else: | ||||
|             die(b'Unknown file command: %s' % line) | ||||
|         path = c_style_unescape(path) | ||||
|         path = fixup_path_from_git(path) | ||||
|         files[path] = files.get(path, {}) | ||||
|         files[path].update(f) | ||||
|  | ||||
| @@ -1135,10 +1192,20 @@ def parse_commit(parser): | ||||
|         extra[b'branch'] = hgref(branch) | ||||
|  | ||||
|     if mode == 'hg': | ||||
|         # add some extra that hg-git adds (almost) unconditionally | ||||
|         # see also https://foss.heptapod.net/mercurial/hg-git/-/merge_requests/211 | ||||
|         # NOTE it could be changed to another value below | ||||
|         # actually, it is *almost* unconditionally, and only done if the commit | ||||
|         # is deduced to originate in git.  However, the latter is based on | ||||
|         # presence/absence of HG markers in commit "extra headers". | ||||
|         # The latter can not be handled here, and so this can not be correctly | ||||
|         # reproduced. | ||||
|         # extra[b'hg-git-rename-source'] = b'git' | ||||
|         i = data.find(b'\n--HG--\n') | ||||
|         if i >= 0: | ||||
|             tmp = data[i + len(b'\n--HG--\n'):].strip() | ||||
|             for k, v in [e.split(b' : ', 1) for e in tmp.split(b'\n')]: | ||||
|                 # NOTE no longer used in hg-git, a HG:rename extra header is used | ||||
|                 if k == b'rename': | ||||
|                     old, new = v.split(b' => ', 1) | ||||
|                     files[new]['rename'] = old | ||||
| @@ -1326,7 +1393,10 @@ def checkheads(repo, remote, p_revs, force): | ||||
| def push_unsafe(repo, remote, p_revs, force): | ||||
|  | ||||
|     fci = discovery.findcommonincoming | ||||
|     commoninc = fci(repo, remote, force=force) | ||||
|     if check_version(4, 5): | ||||
|         commoninc = fci(repo, remote, force=force, ancestorsof=list(p_revs)) | ||||
|     else: | ||||
|         commoninc = fci(repo, remote, force=force) | ||||
|     common, _, remoteheads = commoninc | ||||
|     fco = discovery.findcommonoutgoing | ||||
|     outgoing = fco(repo, remote, onlyheads=list(p_revs), commoninc=commoninc, force=force) | ||||
| @@ -1357,12 +1427,6 @@ def push_unsafe(repo, remote, p_revs, force): | ||||
|     else: | ||||
|         ret = remote.addchangegroup(cg, b'push', repo.url()) | ||||
|  | ||||
|     phases = remote.listkeys(b'phases') | ||||
|     if phases: | ||||
|         for head in p_revs: | ||||
|             # update to public | ||||
|             remote.pushkey(b'phases', hghex(head), b'1', b'0') | ||||
|  | ||||
|     return ret | ||||
|  | ||||
| def push(repo, remote, p_revs, force): | ||||
| @@ -1397,6 +1461,7 @@ def do_push_hg(parser): | ||||
|     global parsed_refs, parsed_tags | ||||
|     p_bmarks = [] | ||||
|     p_revs = {} | ||||
|     ok_refs = [] | ||||
|  | ||||
|     parsed_refs = {} | ||||
|     parsed_tags = {} | ||||
| @@ -1443,7 +1508,7 @@ def do_push_hg(parser): | ||||
|                 continue | ||||
|  | ||||
|             p_revs[bnode] = ref | ||||
|             puts(b"ok %s" % ref) | ||||
|             ok_refs.append(ref) | ||||
|         elif ref.startswith(b'refs/heads/'): | ||||
|             bmark = ref[len(b'refs/heads/'):] | ||||
|             new = node | ||||
| @@ -1453,14 +1518,14 @@ def do_push_hg(parser): | ||||
|                 puts(b"ok %s up to date" % ref) | ||||
|                 continue | ||||
|  | ||||
|             puts(b"ok %s" % ref) | ||||
|             ok_refs.append(ref) | ||||
|             if not bookmark_is_fake(bmark, parser.repo._bookmarks): | ||||
|                 p_bmarks.append((ref, bmark, old, new)) | ||||
|  | ||||
|             p_revs[bnode] = ref | ||||
|         elif ref.startswith(b'refs/tags/'): | ||||
|             if dry_run: | ||||
|                 puts(b"ok %s" % ref) | ||||
|                 ok_refs.append(ref) | ||||
|                 continue | ||||
|             tag = ref[len(b'refs/tags/'):] | ||||
|             tag = hgref(tag) | ||||
| @@ -1487,14 +1552,15 @@ def do_push_hg(parser): | ||||
|                 fp.write(b'%s %s\n' % (node, tag)) | ||||
|                 fp.close() | ||||
|             p_revs[bnode] = ref | ||||
|             puts(b"ok %s" % ref) | ||||
|             ok_refs.append(ref) | ||||
|         else: | ||||
|             # transport-helper/fast-export bugs | ||||
|             continue | ||||
|  | ||||
|     if dry_run: | ||||
|         if peer: | ||||
|             checkheads(parser.repo, peer, p_revs, force_push) | ||||
|         if not peer or checkheads(parser.repo, peer, p_revs, force_push): | ||||
|             for ref in ok_refs: | ||||
|                 puts(b"ok %s" % ref) | ||||
|         return | ||||
|  | ||||
|     success = True | ||||
| @@ -1515,12 +1581,18 @@ def do_push_hg(parser): | ||||
|             if not peer.pushkey(b'bookmarks', bmark, old, new): | ||||
|                 success = False | ||||
|                 puts(b"error %s" % ref) | ||||
|                 ok_refs.remove(ref) | ||||
|     else: | ||||
|         # update local bookmarks | ||||
|         for ref, bmark, old, new in p_bmarks: | ||||
|             if not bookmarks.pushbookmark(parser.repo, bmark, old, new): | ||||
|                 success = False | ||||
|                 puts(b"error %s" % ref) | ||||
|                 ok_refs.remove(ref) | ||||
|  | ||||
|     # update rest of the refs | ||||
|     for ref in ok_refs: | ||||
|         puts(b"ok %s" % ref) | ||||
|  | ||||
|     return success | ||||
|  | ||||
| @@ -1604,10 +1676,7 @@ def do_push_refspec(parser, refspec, revs): | ||||
|             tmpfastexport = open(os.path.join(marksdir, b'git-fast-export-%d' % (os.getpid())), 'w+b') | ||||
|             subprocess.check_call(cmd, stdin=None, stdout=tmpfastexport) | ||||
|             try: | ||||
|                 import imp | ||||
|                 sys.dont_write_bytecode = True | ||||
|                 ctx.hghelper = imp.load_source('hghelper', \ | ||||
|                     os.path.join(os.path.dirname(__file__), 'git-hg-helper')) | ||||
|                 ctx.hghelper = import_sibling('hghelper', 'git-hg-helper') | ||||
|                 ctx.hghelper.init_git(gitdir) | ||||
|                 ctx.gitmarks = ctx.hghelper.GitMarks(tmpmarks) | ||||
|                 # let processing know it should not bother pushing if not requested | ||||
| @@ -1729,8 +1798,7 @@ def fix_path(alias, repo, orig_url): | ||||
|     url = compat.urlparse(orig_url, b'file') | ||||
|     if url.scheme != b'file' or os.path.isabs(os.path.expanduser(url.path)): | ||||
|         return | ||||
|     abs_url = compat.urljoin(b"%s/" % compat.getcwd(), orig_url) | ||||
|     cmd = ['git', 'config', b'remote.%s.url' % alias, b"hg::%s" % abs_url] | ||||
|     cmd = ['git', 'config', b'remote.%s.url' % alias, b"hg::%s" % os.path.abspath(orig_url)] | ||||
|     subprocess.call(cmd) | ||||
|  | ||||
| def select_private_refs(alias): | ||||
| @@ -1845,6 +1913,7 @@ def main(args): | ||||
|     global capability_push | ||||
|     global remove_username_quotes | ||||
|     global marksdir | ||||
|     global dotfile_suffix | ||||
|  | ||||
|     marks = None | ||||
|     is_tmp = False | ||||
| @@ -1864,6 +1933,7 @@ def main(args): | ||||
|     track_branches = get_config_bool('remote-hg.track-branches', True) | ||||
|     capability_push = get_config_bool('remote-hg.capability-push', True) | ||||
|     remove_username_quotes = get_config_bool('remote-hg.remove-username-quotes', True) | ||||
|     dotfile_suffix = get_config('remote-hg.dotfile-suffix').strip() or b'_' | ||||
|     force_push = False | ||||
|  | ||||
|     if hg_git_compat: | ||||
| @@ -1908,7 +1978,7 @@ def main(args): | ||||
|         fix_path(alias, peer or repo, url) | ||||
|  | ||||
|     marks_path = os.path.join(marksdir, b'marks-hg') | ||||
|     marks = Marks(marks_path, repo) | ||||
|     marks = Marks(marks_path) | ||||
|  | ||||
|     if sys.platform == 'win32': | ||||
|         import msvcrt | ||||
|   | ||||
							
								
								
									
										2
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								setup.py
									
									
									
									
									
								
							| @@ -3,7 +3,7 @@ | ||||
| import setuptools | ||||
|  | ||||
| # strip leading v | ||||
| version = 'v1.0.3.2'[1:] | ||||
| version = 'v1.0.5'[1:] | ||||
|  | ||||
| # check for released version | ||||
| assert (len(version) > 0) | ||||
|   | ||||
							
								
								
									
										0
									
								
								test/.gitignore → t/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								test/.gitignore → t/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,9 +1,9 @@ | ||||
| RM ?= rm -f | ||||
| 
 | ||||
| T = main.t main-push.t bidi.t helper.t | ||||
| TEST_DIRECTORY := $(CURDIR) | ||||
| SHARNESS_TEST_DIRECTORY := $(CURDIR) | ||||
| 
 | ||||
| export TEST_DIRECTORY | ||||
| export SHARNESS_TEST_DIRECTORY | ||||
| 
 | ||||
| all: test | ||||
| 
 | ||||
| @@ -11,7 +11,7 @@ test: $(T) | ||||
| 	$(MAKE) clean | ||||
| 
 | ||||
| $(T): | ||||
| 	$(SHELL) $@ $(TEST_OPTS) | ||||
| 	./$@ $(TEST_OPTS) | ||||
| 
 | ||||
| clean: | ||||
| 	$(RM) -r 'trash directory'.* test-results | ||||
| @@ -1,4 +1,4 @@ | ||||
| #!/bin/sh | ||||
| #!/bin/bash | ||||
| # | ||||
| # Copyright (c) 2012 Felipe Contreras | ||||
| # | ||||
| @@ -8,14 +8,7 @@ | ||||
| 
 | ||||
| test_description='Test bidirectionality of remote-hg' | ||||
| 
 | ||||
| test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||
| . "$TEST_DIRECTORY"/test-lib.sh | ||||
| 
 | ||||
| if ! test_have_prereq PYTHON | ||||
| then | ||||
| 	skip_all='skipping remote-hg tests; python with mercurial not available' | ||||
| 	test_done | ||||
| fi | ||||
| . "$(dirname "$0")"/test-lib.sh | ||||
| 
 | ||||
| # clone to a git repo | ||||
| git_clone () { | ||||
							
								
								
									
										60
									
								
								t/expected/converged merge/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								t/expected/converged merge/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 2 | ||||
| A | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 7 | ||||
| origin | ||||
| M 100644 :1 afile | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 2 | ||||
| C | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 3 +0000 | ||||
| committer A U Thor <author@example.com> 3 +0000 | ||||
| data 5 | ||||
| A->C | ||||
| from :2 | ||||
| M 100644 :3 afile | ||||
|  | ||||
| blob | ||||
| mark :5 | ||||
| data 2 | ||||
| B | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :6 | ||||
| author A U Thor <author@example.com> 1 +0000 | ||||
| committer A U Thor <author@example.com> 1 +0000 | ||||
| data 5 | ||||
| A->B | ||||
| from :2 | ||||
| M 100644 :5 afile | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :7 | ||||
| author A U Thor <author@example.com> 2 +0000 | ||||
| committer A U Thor <author@example.com> 2 +0000 | ||||
| data 5 | ||||
| B->C | ||||
| from :6 | ||||
| M 100644 :3 afile | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :8 | ||||
| author A U Thor <author@example.com> 4 +0000 | ||||
| committer A U Thor <author@example.com> 4 +0000 | ||||
| data 6 | ||||
| merge | ||||
| from :4 | ||||
| merge :7 | ||||
|  | ||||
							
								
								
									
										67
									
								
								t/expected/converged merge/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								t/expected/converged merge/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| changeset:   9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    331ac2e605f2e6092ccb3802244a65b71f3be726 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| origin | ||||
|  | ||||
|  | ||||
| changeset:   ead35d346ecb18ce9d9d54604ff62b41caa196ce | ||||
| phase:       draft | ||||
| parent:      9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    894f8ad9a84f743d52747963d0b9f4e9cf37d489 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:01 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| A->B | ||||
|  | ||||
|  | ||||
| changeset:   541c7bc8b2d01c8bf71b2298d17edcda120e49bf | ||||
| phase:       draft | ||||
| parent:      ead35d346ecb18ce9d9d54604ff62b41caa196ce | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    04dae4001cb1fb2384111589720617c4b742044c | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:02 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| B->C | ||||
|  | ||||
|  | ||||
| changeset:   5694aadcd7171ecb9768b13e29d027e22a360d44 | ||||
| phase:       draft | ||||
| parent:      9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    6efc6bb8e097947aa212887bdb01fb89dfa3de13 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:03 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| A->C | ||||
|  | ||||
|  | ||||
| changeset:   9ee75b4362cc15f9110d6538b2f1c9f0cf14825a | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      5694aadcd7171ecb9768b13e29d027e22a360d44 | ||||
| parent:      541c7bc8b2d01c8bf71b2298d17edcda120e49bf | ||||
| manifest:    eb9f4687448653e876d787cd6f2e59140680ff09 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:04 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| merge | ||||
|  | ||||
|  | ||||
							
								
								
									
										56
									
								
								t/expected/encoding/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								t/expected/encoding/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 12 | ||||
| add älphà | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 5 | ||||
| beta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author tést èncödîng <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 9 | ||||
| add beta | ||||
| from :2 | ||||
| M 100644 :3 beta | ||||
|  | ||||
| blob | ||||
| mark :5 | ||||
| data 6 | ||||
| gamma | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :6 | ||||
| author tést èncödîng <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 12 | ||||
| add gämmâ | ||||
| from :4 | ||||
| M 100644 :5 gamma | ||||
|  | ||||
| blob | ||||
| mark :7 | ||||
| data 6 | ||||
| delta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :8 | ||||
| author tést èncödîng <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 12 | ||||
| add déltà | ||||
| from :6 | ||||
| M 100644 :7 delta | ||||
|  | ||||
							
								
								
									
										58
									
								
								t/expected/encoding/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								t/expected/encoding/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| changeset:   6674f1c866b5c428db4acde16404c14077889646 | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      7e9fd3fd2f75d7de4bf3d77c47f192a51927ac28 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    ea49f93388380ead5601c8fcbfa187516e7c2ed8 | ||||
| user:        tést èncödîng <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      delta | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add déltà | ||||
|  | ||||
|  | ||||
| changeset:   7e9fd3fd2f75d7de4bf3d77c47f192a51927ac28 | ||||
| phase:       draft | ||||
| parent:      99c5adad03b9a9935e181f4be91ff7693a790110 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    f580e7da3673c137370da2b931a1dee83590d7b4 | ||||
| user:        tést èncödîng <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      gamma | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add gämmâ | ||||
|  | ||||
|  | ||||
| changeset:   99c5adad03b9a9935e181f4be91ff7693a790110 | ||||
| phase:       draft | ||||
| parent:      1e3e49d2cc8feaad4942d100108f20f207742d3a | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    f0bd6fbafbaebe4bb59c35108428f6fce152431d | ||||
| user:        tést èncödîng <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      beta | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add beta | ||||
|  | ||||
|  | ||||
| changeset:   1e3e49d2cc8feaad4942d100108f20f207742d3a | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add älphà | ||||
|  | ||||
|  | ||||
							
								
								
									
										32
									
								
								t/expected/executable bit/log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								t/expected/executable bit/log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 10 | ||||
| add alpha | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :3 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 19 | ||||
| set executable bit | ||||
| from :2 | ||||
| M 100755 :1 alpha | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 21 | ||||
| clear executable bit | ||||
| from :3 | ||||
| M 100644 :1 alpha | ||||
|  | ||||
							
								
								
									
										46
									
								
								t/expected/executable bit/output
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								t/expected/executable bit/output
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| changeset:   1efb93106a36bf71352ab04e769a3422522cf946 | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      d7cae8b1fdab97568ba5eca44ca2bf5a44d7c394 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    51e6255d794f794a8c4e0f03edf264444e3c5ce7 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files:       alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| clear executable bit | ||||
|  | ||||
|  | ||||
| changeset:   d7cae8b1fdab97568ba5eca44ca2bf5a44d7c394 | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    e4bf4ef5e9aea7a6a57573e533a5519bd062f144 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files:       alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| set executable bit | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
| 644   alpha | ||||
| 644   alpha | ||||
							
								
								
									
										60
									
								
								t/expected/file removal/log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								t/expected/file removal/log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 10 | ||||
| add alpha | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 5 | ||||
| beta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 9 | ||||
| add beta | ||||
| from :2 | ||||
| M 100644 :3 beta | ||||
|  | ||||
| blob | ||||
| mark :5 | ||||
| data 5 | ||||
| blah | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :6 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 8 | ||||
| add foo | ||||
| from :4 | ||||
| M 100644 :5 foo/bar | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :7 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 13 | ||||
| remove alpha | ||||
| from :6 | ||||
| D alpha | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :8 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 15 | ||||
| remove foo/bar | ||||
| from :7 | ||||
| D foo/bar | ||||
|  | ||||
							
								
								
									
										75
									
								
								t/expected/file removal/output
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								t/expected/file removal/output
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| changeset:   54f595cbdf1f516dc3b2b25faa6f051aae712f5d | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      7fe32a9185c6d37db430ee5248cdb2ae66582478 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    3f83f42fa00fb0cac14a83aa48baac2f287a9329 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files-:      foo/bar | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| remove foo/bar | ||||
|  | ||||
|  | ||||
| changeset:   7fe32a9185c6d37db430ee5248cdb2ae66582478 | ||||
| phase:       draft | ||||
| parent:      a21fd0b26a555427c2ea72f8ed37190f6216f705 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    cd10925837609b99d345c44c85bd1f73d742cbbc | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files-:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| remove alpha | ||||
|  | ||||
|  | ||||
| changeset:   a21fd0b26a555427c2ea72f8ed37190f6216f705 | ||||
| phase:       draft | ||||
| parent:      7cd99375c843931bd8959b766a94e050f428512b | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    a6ee442a94bfc6fb0b7d717183bb8b4534ca4ccd | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      foo/bar | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add foo | ||||
|  | ||||
|  | ||||
| changeset:   7cd99375c843931bd8959b766a94e050f428512b | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    f0bd6fbafbaebe4bb59c35108428f6fce152431d | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      beta | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add beta | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
| beta | ||||
| foo/bar | ||||
| beta | ||||
							
								
								
									
										32
									
								
								t/expected/git tags/log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								t/expected/git tags/log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| changeset:   7cd99375c843931bd8959b766a94e050f428512b | ||||
| bookmark:    master | ||||
| tag:         beta | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    f0bd6fbafbaebe4bb59c35108428f6fce152431d | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      beta | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add beta | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| tag:         alpha | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
							
								
								
									
										141
									
								
								t/expected/hg author/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								t/expected/hg author/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/not-master | ||||
| commit refs/heads/not-master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 10 | ||||
| add alpha | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 5 | ||||
| beta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author test <none@none> 0 +0000 | ||||
| committer test <none@none> 0 +0000 | ||||
| data 9 | ||||
| add beta | ||||
| from :2 | ||||
| M 100644 :3 beta | ||||
|  | ||||
| blob | ||||
| mark :5 | ||||
| data 11 | ||||
| beta | ||||
| gamma | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :6 | ||||
| author test ext:(%20%28comment%29) <test@example.com> 0 +0000 | ||||
| committer test ext:(%20%28comment%29) <test@example.com> 0 +0000 | ||||
| data 12 | ||||
| modify beta | ||||
| from :4 | ||||
| M 100644 :5 beta | ||||
|  | ||||
| blob | ||||
| mark :7 | ||||
| data 6 | ||||
| gamma | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :8 | ||||
| author  <test@example.com> 0 +0000 | ||||
| committer  <test@example.com> 0 +0000 | ||||
| data 10 | ||||
| add gamma | ||||
| from :6 | ||||
| M 100644 :7 gamma | ||||
|  | ||||
| blob | ||||
| mark :9 | ||||
| data 6 | ||||
| delta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :10 | ||||
| author name <test@example.com> 0 +0000 | ||||
| committer name <test@example.com> 0 +0000 | ||||
| data 10 | ||||
| add delta | ||||
| from :8 | ||||
| M 100644 :9 delta | ||||
|  | ||||
| blob | ||||
| mark :11 | ||||
| data 8 | ||||
| epsilon | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :12 | ||||
| author name <test@example.com> 0 +0000 | ||||
| committer name <test@example.com> 0 +0000 | ||||
| data 12 | ||||
| add epsilon | ||||
| from :10 | ||||
| M 100644 :11 epsilon | ||||
|  | ||||
| blob | ||||
| mark :13 | ||||
| data 5 | ||||
| zeta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :14 | ||||
| author test <none@none> 0 +0000 | ||||
| committer test <none@none> 0 +0000 | ||||
| data 9 | ||||
| add zeta | ||||
| from :12 | ||||
| M 100644 :13 zeta | ||||
|  | ||||
| blob | ||||
| mark :15 | ||||
| data 4 | ||||
| eta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :16 | ||||
| author test <test@example.com> 0 +0000 | ||||
| committer test <test@example.com> 0 +0000 | ||||
| data 8 | ||||
| add eta | ||||
| from :14 | ||||
| M 100644 :15 eta | ||||
|  | ||||
| blob | ||||
| mark :17 | ||||
| data 6 | ||||
| theta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :18 | ||||
| author test ?test@example.com <test ?test@example.com> 0 +0000 | ||||
| committer test ?test@example.com <test ?test@example.com> 0 +0000 | ||||
| data 10 | ||||
| add theta | ||||
| from :16 | ||||
| M 100644 :17 theta | ||||
|  | ||||
| blob | ||||
| mark :19 | ||||
| data 5 | ||||
| iota | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :20 | ||||
| author test ext:(%20example%20%3Cdot%3E%20com%3E) <test ?at> 0 +0000 | ||||
| committer test ext:(%20example%20%3Cdot%3E%20com%3E) <test ?at> 0 +0000 | ||||
| data 9 | ||||
| add iota | ||||
| from :18 | ||||
| M 100644 :19 iota | ||||
|  | ||||
							
								
								
									
										134
									
								
								t/expected/hg author/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								t/expected/hg author/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| changeset:   307c03466a07cccafaafc991f36d695d6ad595f3 | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      5832614d351449a2f8d6f7ccbef4877c2b18cbe0 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    e8f1b3ae088bdd25e3570a4953ccb6b948524473 | ||||
| user:        test <test ?at> example <dot> com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      iota | ||||
| extra:       branch=default | ||||
| description: | ||||
| add iota | ||||
|  | ||||
|  | ||||
| changeset:   5832614d351449a2f8d6f7ccbef4877c2b18cbe0 | ||||
| phase:       draft | ||||
| parent:      e52ded4aca5d210ed58c63158d64fb911876f345 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    7e4875db7e2970c529f462520121d333e514bf4d | ||||
| user:        test ?test@example.com <test ?test@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      theta | ||||
| extra:       branch=default | ||||
| description: | ||||
| add theta | ||||
|  | ||||
|  | ||||
| changeset:   e52ded4aca5d210ed58c63158d64fb911876f345 | ||||
| phase:       draft | ||||
| parent:      9a34ba7d552e8b73ad306baf1d1eb83de0f74c12 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    ef03e54a9916ac3158c9686503dd4f609c26b3ec | ||||
| user:        test <test@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      eta | ||||
| extra:       branch=default | ||||
| description: | ||||
| add eta | ||||
|  | ||||
|  | ||||
| changeset:   9a34ba7d552e8b73ad306baf1d1eb83de0f74c12 | ||||
| phase:       draft | ||||
| parent:      6281edc25b9fe9538407726f044a9a61ac7ba5bc | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    616201b85baf7ed02d41f6a7deb04c52009d8483 | ||||
| user:        test | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      zeta | ||||
| extra:       branch=default | ||||
| description: | ||||
| add zeta | ||||
|  | ||||
|  | ||||
| changeset:   6281edc25b9fe9538407726f044a9a61ac7ba5bc | ||||
| phase:       draft | ||||
| parent:      4c7841053c633cb51f8375555d08b6bea54fc4cb | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    c703b3d7be8a0638047142f57ff83d4e94b5d1fa | ||||
| user:        name <test@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      epsilon | ||||
| extra:       branch=default | ||||
| description: | ||||
| add epsilon | ||||
|  | ||||
|  | ||||
| changeset:   4c7841053c633cb51f8375555d08b6bea54fc4cb | ||||
| phase:       draft | ||||
| parent:      fa8f26586397dd4797842e9300c8db221fe5514d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    300b54001cbfa5d027b4bccdb594ccb463adb55d | ||||
| user:        name <test@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      delta | ||||
| extra:       branch=default | ||||
| description: | ||||
| add delta | ||||
|  | ||||
|  | ||||
| changeset:   fa8f26586397dd4797842e9300c8db221fe5514d | ||||
| phase:       draft | ||||
| parent:      2708ff417fb7e2c0a4f9596286c0a398553fa793 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    45b0c483a79307d14f7e234feb78776478f828ec | ||||
| user:        <test@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      gamma | ||||
| extra:       branch=default | ||||
| description: | ||||
| add gamma | ||||
|  | ||||
|  | ||||
| changeset:   2708ff417fb7e2c0a4f9596286c0a398553fa793 | ||||
| phase:       draft | ||||
| parent:      8c51e5fe974fe1cc63a56bbfad343f9ede6bed30 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    c305998040b12e956b998318982c9eb92d2d7b28 | ||||
| user:        test <test@example.com> (comment) | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files:       beta | ||||
| extra:       branch=default | ||||
| description: | ||||
| modify beta | ||||
|  | ||||
|  | ||||
| changeset:   8c51e5fe974fe1cc63a56bbfad343f9ede6bed30 | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    f0bd6fbafbaebe4bb59c35108428f6fce152431d | ||||
| user:        test | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      beta | ||||
| extra:       branch=default | ||||
| description: | ||||
| add beta | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| bookmark:    not-master | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
							
								
								
									
										38
									
								
								t/expected/hg branch/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								t/expected/hg branch/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/not-master | ||||
| commit refs/heads/not-master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 10 | ||||
| add alpha | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :3 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 52 | ||||
| rename alpha to beta | ||||
|  | ||||
| --HG-- | ||||
| rename : alpha => beta | ||||
| from :2 | ||||
| D alpha | ||||
| M 100644 :1 beta | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 44 | ||||
| started branch gamma | ||||
|  | ||||
| --HG-- | ||||
| branch : gamma | ||||
| from :3 | ||||
|  | ||||
							
								
								
									
										44
									
								
								t/expected/hg branch/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								t/expected/hg branch/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| changeset:   3320583a8de0b31511f499a4ab3426bee1a7f478 | ||||
| branch:      gamma | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      5889597089fea2d144989baa9427d1a080293fdb | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    e353b4d5282d044ad738398fd32d0b684d04a14b | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| extra:       branch=gamma | ||||
| description: | ||||
| started branch gamma | ||||
|  | ||||
|  | ||||
| changeset:   5889597089fea2d144989baa9427d1a080293fdb | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    e353b4d5282d044ad738398fd32d0b684d04a14b | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      beta | ||||
| files-:      alpha | ||||
| extra:       branch=default | ||||
| description: | ||||
| rename alpha to beta | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| bookmark:    not-master | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
							
								
								
									
										33
									
								
								t/expected/hg tags/output
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								t/expected/hg tags/output
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| alpha | ||||
| changeset:   16869bbe54be9f8082a8aec346de09f6c05cf1de | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    26f8145fb5b20cc6f70dd131b646f95ab79738c0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      .hgtags | ||||
| extra:       branch=default | ||||
| description: | ||||
| Added tag alpha for changeset 362b656574c3 | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| bookmark:    not-master | ||||
| tag:         alpha | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
| 362b656574c3c9e89fa7f2d7a943091dc93bce4d alpha | ||||
							
								
								
									
										51
									
								
								t/expected/merge conflict 1/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								t/expected/merge conflict 1/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 2 | ||||
| A | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 7 | ||||
| origin | ||||
| M 100644 :1 afile | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 2 | ||||
| C | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 2 +0000 | ||||
| committer A U Thor <author@example.com> 2 +0000 | ||||
| data 5 | ||||
| A->C | ||||
| from :2 | ||||
| M 100644 :3 afile | ||||
|  | ||||
| blob | ||||
| mark :5 | ||||
| data 2 | ||||
| B | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :6 | ||||
| author A U Thor <author@example.com> 1 +0000 | ||||
| committer A U Thor <author@example.com> 1 +0000 | ||||
| data 5 | ||||
| A->B | ||||
| from :2 | ||||
| M 100644 :5 afile | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :7 | ||||
| author A U Thor <author@example.com> 3 +0000 | ||||
| committer A U Thor <author@example.com> 3 +0000 | ||||
| data 11 | ||||
| merge to C | ||||
| from :4 | ||||
| merge :6 | ||||
|  | ||||
							
								
								
									
										54
									
								
								t/expected/merge conflict 1/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								t/expected/merge conflict 1/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| changeset:   9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    331ac2e605f2e6092ccb3802244a65b71f3be726 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| origin | ||||
|  | ||||
|  | ||||
| changeset:   ead35d346ecb18ce9d9d54604ff62b41caa196ce | ||||
| phase:       draft | ||||
| parent:      9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    894f8ad9a84f743d52747963d0b9f4e9cf37d489 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:01 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| A->B | ||||
|  | ||||
|  | ||||
| changeset:   d585ac55494928500f510b965b878d47f9ee60f6 | ||||
| phase:       draft | ||||
| parent:      9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    6efc6bb8e097947aa212887bdb01fb89dfa3de13 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:02 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| A->C | ||||
|  | ||||
|  | ||||
| changeset:   c6ab734e24c39948e5a25713b48f4972c960ff8b | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      d585ac55494928500f510b965b878d47f9ee60f6 | ||||
| parent:      ead35d346ecb18ce9d9d54604ff62b41caa196ce | ||||
| manifest:    96bedb13781f1b9d729a2210a530f0c5c68f42e6 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:03 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| merge to C | ||||
|  | ||||
|  | ||||
							
								
								
									
										52
									
								
								t/expected/merge conflict 2/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								t/expected/merge conflict 2/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 2 | ||||
| A | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 7 | ||||
| origin | ||||
| M 100644 :1 afile | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 2 | ||||
| C | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 2 +0000 | ||||
| committer A U Thor <author@example.com> 2 +0000 | ||||
| data 5 | ||||
| A->C | ||||
| from :2 | ||||
| M 100644 :3 afile | ||||
|  | ||||
| blob | ||||
| mark :5 | ||||
| data 2 | ||||
| B | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :6 | ||||
| author A U Thor <author@example.com> 1 +0000 | ||||
| committer A U Thor <author@example.com> 1 +0000 | ||||
| data 5 | ||||
| A->B | ||||
| from :2 | ||||
| M 100644 :5 afile | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :7 | ||||
| author A U Thor <author@example.com> 3 +0000 | ||||
| committer A U Thor <author@example.com> 3 +0000 | ||||
| data 11 | ||||
| merge to B | ||||
| from :4 | ||||
| merge :6 | ||||
| M 100644 :5 afile | ||||
|  | ||||
							
								
								
									
										54
									
								
								t/expected/merge conflict 2/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								t/expected/merge conflict 2/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| changeset:   9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    331ac2e605f2e6092ccb3802244a65b71f3be726 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| origin | ||||
|  | ||||
|  | ||||
| changeset:   ead35d346ecb18ce9d9d54604ff62b41caa196ce | ||||
| phase:       draft | ||||
| parent:      9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    894f8ad9a84f743d52747963d0b9f4e9cf37d489 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:01 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| A->B | ||||
|  | ||||
|  | ||||
| changeset:   d585ac55494928500f510b965b878d47f9ee60f6 | ||||
| phase:       draft | ||||
| parent:      9a6668f453c3003b71e11bb8d7572af57a7ce891 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    6efc6bb8e097947aa212887bdb01fb89dfa3de13 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:02 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| A->C | ||||
|  | ||||
|  | ||||
| changeset:   542b187b70e70dc759631d1065794f3c2c5a3e7b | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      d585ac55494928500f510b965b878d47f9ee60f6 | ||||
| parent:      ead35d346ecb18ce9d9d54604ff62b41caa196ce | ||||
| manifest:    0907d7dbc98790102fa6cb91b68b271ef0bc5b64 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:03 1970 +0000 | ||||
| files:       afile | ||||
| extra:       branch=default | ||||
| description: | ||||
| merge to B | ||||
|  | ||||
|  | ||||
							
								
								
									
										27
									
								
								t/expected/rename/git-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								t/expected/rename/git-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 10 | ||||
| add alpha | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| commit refs/heads/master | ||||
| mark :3 | ||||
| author A U Thor <author@example.com> 0 +0000 | ||||
| committer A U Thor <author@example.com> 0 +0000 | ||||
| data 52 | ||||
| rename alpha to beta | ||||
|  | ||||
| --HG-- | ||||
| rename : alpha => beta | ||||
| from :2 | ||||
| D alpha | ||||
| M 100644 :1 beta | ||||
|  | ||||
							
								
								
									
										29
									
								
								t/expected/rename/hg-log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								t/expected/rename/hg-log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| changeset:   a985b184598fd779e53576c65c5dd1d274736c73 | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      0558a161e3ca0d59f5f165e3182402d9f1e574a8 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    e353b4d5282d044ad738398fd32d0b684d04a14b | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      beta | ||||
| files-:      alpha | ||||
| extra:       branch=default | ||||
| description: | ||||
| rename alpha to beta | ||||
|  | ||||
|  | ||||
| changeset:   0558a161e3ca0d59f5f165e3182402d9f1e574a8 | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Thu Jan 01 00:00:00 1970 +0000 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
							
								
								
									
										27
									
								
								t/expected/symlink/log
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								t/expected/symlink/log
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| blob | ||||
| mark :1 | ||||
| data 6 | ||||
| alpha | ||||
|  | ||||
| reset refs/heads/master | ||||
| commit refs/heads/master | ||||
| mark :2 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 10 | ||||
| add alpha | ||||
| M 100644 :1 alpha | ||||
|  | ||||
| blob | ||||
| mark :3 | ||||
| data 5 | ||||
| alpha | ||||
| commit refs/heads/master | ||||
| mark :4 | ||||
| author A U Thor <author@example.com> 1167600600 +0230 | ||||
| committer C O Mitter <committer@example.com> 1167600600 +0230 | ||||
| data 9 | ||||
| add beta | ||||
| from :2 | ||||
| M 120000 :3 beta | ||||
|  | ||||
							
								
								
									
										32
									
								
								t/expected/symlink/output
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								t/expected/symlink/output
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| changeset:   87cbc97576079d3dfef04c678bfc8ab69999ebdf | ||||
| bookmark:    master | ||||
| tag:         tip | ||||
| phase:       draft | ||||
| parent:      362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    4950f48a7f5b0ce6f31c2f4307e296dbac652026 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      beta | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add beta | ||||
|  | ||||
|  | ||||
| changeset:   362b656574c3c9e89fa7f2d7a943091dc93bce4d | ||||
| phase:       draft | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| parent:      -0000000000000000000000000000000000000000 | ||||
| manifest:    8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0 | ||||
| user:        A U Thor <author@example.com> | ||||
| date:        Mon Jan 01 00:00:00 2007 +0230 | ||||
| files+:      alpha | ||||
| extra:       branch=default | ||||
| extra:       committer=C O Mitter <committer@example.com> 1167600600 -9000 | ||||
| description: | ||||
| add alpha | ||||
|  | ||||
|  | ||||
| 644   alpha | ||||
| 644 @ beta | ||||
| @@ -1,4 +1,4 @@ | ||||
| #!/bin/sh | ||||
| #!/bin/bash | ||||
| # | ||||
| # Copyright (c) 2016 Mark Nauwelaerts | ||||
| # | ||||
| @@ -8,8 +8,7 @@ | ||||
| 
 | ||||
| test_description='Test git-hg-helper' | ||||
| 
 | ||||
| test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||
| . "$TEST_DIRECTORY"/test-lib.sh | ||||
| . "$(dirname "$0")"/test-lib.sh | ||||
| 
 | ||||
| if ! test_have_prereq PYTHON | ||||
| then | ||||
| @@ -100,7 +99,7 @@ test_expect_success 'subcommand repo - with local proxy' ' | ||||
| 	test_cmp expected actual | ||||
| ' | ||||
| 
 | ||||
| test_expect_success 'subcommands hg-rev and git-rev' ' | ||||
| test_expect_success 'subcommands hg-rev and git-rev and mapfile' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
| 
 | ||||
| 	setup_repos && | ||||
| @@ -111,7 +110,9 @@ test_expect_success 'subcommands hg-rev and git-rev' ' | ||||
| 	test -s rev-HEAD && | ||||
| 	git-hg-helper hg-rev `cat rev-HEAD` > hg-HEAD && | ||||
| 	git-hg-helper git-rev `cat hg-HEAD` > git-HEAD && | ||||
| 	test_cmp rev-HEAD git-HEAD | ||||
| 	git-hg-helper mapfile --output mapfile origin && | ||||
| 	test_cmp rev-HEAD git-HEAD && | ||||
| 	grep "`cat rev-HEAD` `cat hg-HEAD`" mapfile | ||||
| 	) | ||||
| ' | ||||
| 
 | ||||
							
								
								
									
										446
									
								
								t/hg-git.t
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										446
									
								
								t/hg-git.t
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,446 @@ | ||||
| #!/bin/bash | ||||
| # | ||||
| # Copyright (c) 2012 Felipe Contreras | ||||
| # | ||||
| # Base commands from hg-git tests: | ||||
| # https://bitbucket.org/durin42/hg-git/src | ||||
| # | ||||
|  | ||||
| # shellcheck disable=SC2016,SC2034,SC2086,SC2164,SC1091 | ||||
|  | ||||
| test_description='Test remote-hg output compared to hg-git' | ||||
|  | ||||
| . "$(dirname "$0")"/test-lib.sh | ||||
|  | ||||
| export EXPECTED_DIR="$SHARNESS_TEST_DIRECTORY/expected" | ||||
|  | ||||
| git_clone () { | ||||
| 	git clone -q "hg::$1" $2 && | ||||
| 	( | ||||
| 	cd $2 && | ||||
| 	git checkout master && | ||||
| 	{ git branch -D default || true ;} | ||||
| 	) | ||||
| } | ||||
|  | ||||
| hg_clone () { | ||||
| 	( | ||||
| 	hg init $2 && | ||||
| 	hg -R $2 bookmark -i master && | ||||
| 	cd $1 && | ||||
| 	git push -q "hg::../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' | ||||
| 	) && | ||||
|  | ||||
| 	(cd $2 && hg -q update) | ||||
| } | ||||
|  | ||||
| hg_push () { | ||||
| 	( | ||||
| 	cd $2 | ||||
| 	git checkout -q -b tmp && | ||||
| 	git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' && | ||||
| 	git branch -D default && | ||||
| 	git checkout -q '@{-1}' && | ||||
| 	{ git branch -q -D tmp 2> /dev/null || true ;} | ||||
| 	) | ||||
| } | ||||
|  | ||||
| hg_log () { | ||||
| 	hg -R $1 log --debug -r 'sort(tip:0, date)' | | ||||
| 		sed -e '/tag: *default/d' -e 's/[0-9]\+:\([0-9a-f]\{40\}\)/\1/' | ||||
| } | ||||
|  | ||||
| git_log () { | ||||
| 	git -C $1 fast-export --branches | ||||
| } | ||||
|  | ||||
| test_cmp_expected () { | ||||
| 	test_cmp "$EXPECTED_DIR/$test_id/$1" "$1" | ||||
| } | ||||
|  | ||||
| cmp_hg_to_git_log () { | ||||
| 	hg_log hgrepo2 > hg-log && | ||||
| 	git_log gitrepo > git-log && | ||||
|  | ||||
| 	test_cmp_expected hg-log && | ||||
| 	test_cmp_expected git-log | ||||
| } | ||||
|  | ||||
| cmp_hg_to_git_log_hgrepo1 () { | ||||
| 	git_clone hgrepo1 gitrepo && | ||||
| 	hg_clone gitrepo hgrepo2 && | ||||
|  | ||||
| 	cmp_hg_to_git_log | ||||
| } | ||||
|  | ||||
| cmp_hg_to_git_manifest () { | ||||
| 	( | ||||
| 	hg_clone gitrepo hgrepo && | ||||
| 	cd hgrepo && | ||||
| 	hg_log . && | ||||
| 	eval "$1" | ||||
| 	) > output && | ||||
|  | ||||
| 	git_clone hgrepo gitrepo2 && | ||||
| 	git_log gitrepo2 > log && | ||||
|  | ||||
| 	test_cmp_expected output && | ||||
| 	test_cmp_expected log | ||||
| } | ||||
|  | ||||
| setup () { | ||||
| 	cat > "$HOME"/.hgrc <<-EOF | ||||
| 	[ui] | ||||
| 	username = A U Thor <author@example.com> | ||||
| 	[defaults] | ||||
| 	commit = -d "0 0" | ||||
| 	tag = -d "0 0" | ||||
| 	EOF | ||||
|  | ||||
| 	cat > "$HOME"/.gitconfig <<-EOF | ||||
| 	[remote-hg] | ||||
| 		hg-git-compat = true | ||||
| 		track-branches = false | ||||
| 		# directly use local repo to avoid push (and hence phase issues) | ||||
| 		shared-marks = false | ||||
| 	EOF | ||||
|  | ||||
| 	export HGEDITOR=true | ||||
| 	export HGMERGE=true | ||||
|  | ||||
| 	export GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" | ||||
| 	export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" | ||||
| } | ||||
|  | ||||
| setup | ||||
|  | ||||
| # save old function | ||||
| eval "old_$(declare -f test_expect_success)" | ||||
|  | ||||
| test_expect_success () { | ||||
| 	local req | ||||
| 	test "$#" = 3 && { req=$1; shift; } || req= | ||||
| 	test_id="$1" | ||||
| 	old_test_expect_success "$req" "$1" " | ||||
| 	test_when_finished \"rm -rf gitrepo* hgrepo*\" && $2" | ||||
| } | ||||
|  | ||||
| test_expect_success 'rename' ' | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo alpha > alpha && | ||||
| 	hg add alpha && | ||||
| 	hg commit -m "add alpha" && | ||||
| 	hg mv alpha beta && | ||||
| 	hg commit -m "rename alpha to beta" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_log_hgrepo1 | ||||
| ' | ||||
|  | ||||
| test_expect_success !WIN 'executable bit' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	echo alpha > alpha && | ||||
| 	chmod 0644 alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	chmod 0755 alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "set executable bit" && | ||||
| 	chmod 0644 alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "clear executable bit" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_manifest "hg manifest -v -r -1; hg manifest -v" | ||||
| ' | ||||
|  | ||||
| test_expect_success !WIN 'symlink' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	ln -s alpha beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_manifest "hg manifest -v" | ||||
| ' | ||||
|  | ||||
| test_expect_success 'merge conflict 1' ' | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo A > afile && | ||||
| 	hg add afile && | ||||
| 	hg ci -m "origin" && | ||||
|  | ||||
| 	echo B > afile && | ||||
| 	hg ci -m "A->B" -d "1 0" && | ||||
|  | ||||
| 	hg up -r0 && | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "A->C" -d "2 0" && | ||||
|  | ||||
| 	hg merge -r1 && | ||||
| 	echo C > afile && | ||||
| 	hg resolve -m afile && | ||||
| 	hg ci -m "merge to C" -d "3 0" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_log_hgrepo1 | ||||
| ' | ||||
|  | ||||
| test_expect_success 'merge conflict 2' ' | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo A > afile && | ||||
| 	hg add afile && | ||||
| 	hg ci -m "origin" && | ||||
|  | ||||
| 	echo B > afile && | ||||
| 	hg ci -m "A->B" -d "1 0" && | ||||
|  | ||||
| 	hg up -r0 && | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "A->C" -d "2 0" && | ||||
|  | ||||
| 	hg merge -r1 || true && | ||||
| 	echo B > afile && | ||||
| 	hg resolve -m afile && | ||||
| 	hg ci -m "merge to B" -d "3 0" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_log_hgrepo1 | ||||
| ' | ||||
|  | ||||
| test_expect_success 'converged merge' ' | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo A > afile && | ||||
| 	hg add afile && | ||||
| 	hg ci -m "origin" && | ||||
|  | ||||
| 	echo B > afile && | ||||
| 	hg ci -m "A->B" -d "1 0" && | ||||
|  | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "B->C" -d "2 0" && | ||||
|  | ||||
| 	hg up -r0 && | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "A->C" -d "3 0" && | ||||
|  | ||||
| 	hg merge -r2 || true && | ||||
| 	hg ci -m "merge" -d "4 0" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_log_hgrepo1 | ||||
| ' | ||||
|  | ||||
| test_expect_success 'encoding' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
|  | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add älphà" && | ||||
|  | ||||
| 	GIT_AUTHOR_NAME="tést èncödîng" && | ||||
| 	export GIT_AUTHOR_NAME && | ||||
| 	echo beta > beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" && | ||||
|  | ||||
| 	echo gamma > gamma && | ||||
| 	git add gamma && | ||||
| 	git commit -m "add gämmâ" && | ||||
|  | ||||
| 	: TODO git config i18n.commitencoding latin-1 && | ||||
| 	echo delta > delta && | ||||
| 	git add delta && | ||||
| 	git commit -m "add déltà" | ||||
| 	) && | ||||
|  | ||||
| 	hg_clone gitrepo hgrepo && | ||||
| 	git_clone hgrepo gitrepo2 && | ||||
|  | ||||
| 	HGENCODING=utf-8 hg_log hgrepo > hg-log && | ||||
| 	git_log gitrepo2 > git-log && | ||||
|  | ||||
| 	test_cmp_expected hg-log && | ||||
| 	test_cmp_expected git-log | ||||
| ' | ||||
|  | ||||
| test_expect_success 'file removal' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	echo beta > beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" | ||||
| 	mkdir foo && | ||||
| 	echo blah > foo/bar && | ||||
| 	git add foo && | ||||
| 	git commit -m "add foo" && | ||||
| 	git rm alpha && | ||||
| 	git commit -m "remove alpha" && | ||||
| 	git rm foo/bar && | ||||
| 	git commit -m "remove foo/bar" | ||||
| 	) && | ||||
|  | ||||
| 	cmp_hg_to_git_manifest "hg manifest -r 3; hg manifest" | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git tags' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	git config receive.denyCurrentBranch ignore && | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	git tag alpha && | ||||
|  | ||||
| 	echo beta > beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" && | ||||
| 	git tag -a -m "added tag beta" beta | ||||
| 	) && | ||||
|  | ||||
| 	hg_clone gitrepo hgrepo && | ||||
| 	hg_log hgrepo > log && | ||||
|  | ||||
| 	test_cmp_expected log | ||||
| ' | ||||
|  | ||||
| test_expect_success 'hg author' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
|  | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	git checkout -q -b not-master | ||||
| 	) && | ||||
|  | ||||
| 	( | ||||
| 	hg_clone gitrepo hgrepo && | ||||
| 	cd hgrepo && | ||||
|  | ||||
| 	hg co master && | ||||
| 	echo beta > beta && | ||||
| 	hg add beta && | ||||
| 	hg commit -u "test" -m "add beta" && | ||||
|  | ||||
| 	echo gamma >> beta && | ||||
| 	hg commit -u "test <test@example.com> (comment)" -m "modify beta" && | ||||
|  | ||||
| 	echo gamma > gamma && | ||||
| 	hg add gamma && | ||||
| 	hg commit -u "<test@example.com>" -m "add gamma" && | ||||
|  | ||||
| 	echo delta > delta && | ||||
| 	hg add delta && | ||||
| 	hg commit -u "name<test@example.com>" -m "add delta" && | ||||
|  | ||||
| 	echo epsilon > epsilon && | ||||
| 	hg add epsilon && | ||||
| 	hg commit -u "name <test@example.com" -m "add epsilon" && | ||||
|  | ||||
| 	echo zeta > zeta && | ||||
| 	hg add zeta && | ||||
| 	hg commit -u " test " -m "add zeta" && | ||||
|  | ||||
| 	echo eta > eta && | ||||
| 	hg add eta && | ||||
| 	hg commit -u "test < test@example.com >" -m "add eta" && | ||||
|  | ||||
| 	echo theta > theta && | ||||
| 	hg add theta && | ||||
| 	hg commit -u "test >test@example.com>" -m "add theta" && | ||||
|  | ||||
| 	echo iota > iota && | ||||
| 	hg add iota && | ||||
| 	hg commit -u "test <test <at> example <dot> com>" -m "add iota" | ||||
| 	) && | ||||
|  | ||||
| 	hg_push hgrepo gitrepo && | ||||
| 	hg_clone gitrepo hgrepo2 && | ||||
|  | ||||
| 	cmp_hg_to_git_log | ||||
| ' | ||||
|  | ||||
| test_expect_success 'hg branch' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
|  | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -q -m "add alpha" && | ||||
| 	git checkout -q -b not-master | ||||
| 	) && | ||||
|  | ||||
| 	( | ||||
| 	hg_clone gitrepo hgrepo && | ||||
|  | ||||
| 	cd hgrepo && | ||||
| 	hg -q co master && | ||||
| 	hg mv alpha beta && | ||||
| 	hg -q commit -m "rename alpha to beta" && | ||||
| 	hg branch gamma | grep -v "permanent and global" && | ||||
| 	hg -q commit -m "started branch gamma" | ||||
| 	) && | ||||
|  | ||||
| 	hg_push hgrepo gitrepo && | ||||
| 	hg_clone gitrepo hgrepo2 && | ||||
|  | ||||
| 	cmp_hg_to_git_log | ||||
| ' | ||||
|  | ||||
| test_expect_success 'hg tags' ' | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
|  | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	git checkout -q -b not-master | ||||
| 	) && | ||||
|  | ||||
| 	( | ||||
| 	hg_clone gitrepo hgrepo && | ||||
|  | ||||
| 	cd hgrepo && | ||||
| 	hg co master && | ||||
| 	hg tag alpha | ||||
| 	) && | ||||
|  | ||||
| 	hg_push hgrepo gitrepo && | ||||
| 	hg_clone gitrepo hgrepo2 && | ||||
|  | ||||
| 	( | ||||
| 	git -C gitrepo tag -l && | ||||
| 	hg_log hgrepo2 && | ||||
| 	cat hgrepo2/.hgtags | ||||
| 	) > output && | ||||
|  | ||||
| 	test_cmp_expected output | ||||
| ' | ||||
|  | ||||
| test_done | ||||
| @@ -1,8 +1,8 @@ | ||||
| #!/bin/bash | ||||
| 
 | ||||
| CAPABILITY_PUSH=t | ||||
| 
 | ||||
| test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||
| . "$TEST_DIRECTORY"/main.t | ||||
| 
 | ||||
| . "$(dirname "$0")"/main.t | ||||
| 
 | ||||
| # .. and some push mode only specific tests | ||||
| 
 | ||||
| @@ -1,4 +1,4 @@ | ||||
| #!/bin/sh | ||||
| #!/bin/bash | ||||
| # | ||||
| # Copyright (c) 2012 Felipe Contreras | ||||
| # | ||||
| @@ -8,8 +8,7 @@ | ||||
| 
 | ||||
| test_description='Test remote-hg' | ||||
| 
 | ||||
| test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||
| . "$TEST_DIRECTORY"/test-lib.sh | ||||
| . "$(dirname "$0")"/test-lib.sh | ||||
| 
 | ||||
| if test "$CAPABILITY_PUSH" = "t" | ||||
| then | ||||
| @@ -20,12 +19,6 @@ else | ||||
| 	git config --global remote-hg.capability-push false | ||||
| fi | ||||
| 
 | ||||
| if ! test_have_prereq PYTHON | ||||
| then | ||||
| 	skip_all='skipping remote-hg tests; python with mercurial not available' | ||||
| 	test_done | ||||
| fi | ||||
| 
 | ||||
| check () { | ||||
| 	echo $3 > expected && | ||||
| 	git --git-dir=$1/.git log --format='%s' -1 $2 > actual && | ||||
| @@ -275,6 +268,41 @@ test_expect_success 'strip' ' | ||||
| 	test_cmp actual expected | ||||
| ' | ||||
| 
 | ||||
| test_expect_success 'dotfiles' ' | ||||
| 	test_when_finished "rm -rf hgrepo gitrepo" && | ||||
| 
 | ||||
| 	( | ||||
| 	hg init hgrepo && | ||||
| 	cd hgrepo && | ||||
| 
 | ||||
| 	echo one >.git && | ||||
| 	echo ONE >.GIT && | ||||
| 	mkdir a && echo two > a/.gitmodules && | ||||
| 	hg add .git .GIT a/.gitmodules && | ||||
| 	hg commit -m zero | ||||
| 	) && | ||||
| 
 | ||||
| 	git clone "hg::hgrepo" gitrepo && | ||||
| 	test_cmp gitrepo/.git_ hgrepo/.git && | ||||
| 	test_cmp gitrepo/.GIT_ hgrepo/.GIT && | ||||
| 	test_cmp gitrepo/a/.gitmodules_ hgrepo/a/.gitmodules && | ||||
| 
 | ||||
| 	( | ||||
| 	cd gitrepo && | ||||
| 	echo three >.git_ && | ||||
| 	echo THREE >.GIT && | ||||
| 	echo four >a/.gitmodules_ && | ||||
| 	git add .git_ .GIT_ a/.gitmodules_ && | ||||
| 	git commit -m one && | ||||
| 	git push | ||||
| 	) && | ||||
| 
 | ||||
| 	hg -R hgrepo update && | ||||
| 	test_cmp gitrepo/.git_ hgrepo/.git && | ||||
| 	test_cmp gitrepo/.GIT_ hgrepo/.GIT && | ||||
| 	test_cmp gitrepo/a/.gitmodules_ hgrepo/a/.gitmodules | ||||
| ' | ||||
| 
 | ||||
| test_expect_success 'remote push with master bookmark' ' | ||||
| 	test_when_finished "rm -rf hgrepo gitrepo*" && | ||||
| 
 | ||||
| @@ -513,7 +541,7 @@ else | ||||
| test_expect_failure "$testcopyrenamedesc" "$testcopyrename" | ||||
| fi | ||||
| 
 | ||||
| test_expect_success 'fetch special filenames' ' | ||||
| test_expect_success !WIN 'fetch special filenames' ' | ||||
| 	test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" && | ||||
| 
 | ||||
| 	LC_ALL=en_US.UTF-8 | ||||
| @@ -652,16 +680,27 @@ test_expect_success 'remote big push' ' | ||||
| 	( | ||||
| 	cd gitrepo && | ||||
| 
 | ||||
| 	check_push 1 --all <<-\EOF | ||||
| 	master | ||||
| 	good_bmark | ||||
| 	branches/good_branch | ||||
| 	new_bmark:new | ||||
| 	branches/new_branch:new | ||||
| 	bad_bmark1:non-fast-forward | ||||
| 	bad_bmark2:non-fast-forward | ||||
| 	branches/bad_branch:non-fast-forward | ||||
| 	EOF | ||||
| 	if test "$CAPABILITY_PUSH" = "t" | ||||
| 	then | ||||
| 		# cap push handles refs one by one | ||||
| 		# so it will still correctly report several ok | ||||
| 		check_push 1 --all <<-\EOF | ||||
| 		master | ||||
| 		good_bmark | ||||
| 		branches/good_branch | ||||
| 		new_bmark:new | ||||
| 		branches/new_branch:new | ||||
| 		bad_bmark1:non-fast-forward | ||||
| 		bad_bmark2:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	else | ||||
| 		check_push 1 --all <<-\EOF | ||||
| 		bad_bmark1:non-fast-forward | ||||
| 		bad_bmark2:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	fi | ||||
| 	) && | ||||
| 
 | ||||
| 	if test "$CAPABILITY_PUSH" = "t" | ||||
| @@ -675,7 +714,8 @@ test_expect_success 'remote big push' ' | ||||
| 		check_bookmark hgrepo good_bmark three && | ||||
| 		check_bookmark hgrepo bad_bmark1 one && | ||||
| 		check_bookmark hgrepo bad_bmark2 one && | ||||
| 		check_bookmark hgrepo new_bmark six | ||||
| 		check_bookmark hgrepo new_bmark six && | ||||
| 		check gitrepo origin/master two | ||||
| 	else | ||||
| 		check_branch hgrepo default one && | ||||
| 		check_branch hgrepo good_branch "good branch" && | ||||
| @@ -684,7 +724,8 @@ test_expect_success 'remote big push' ' | ||||
| 		check_bookmark hgrepo good_bmark one && | ||||
| 		check_bookmark hgrepo bad_bmark1 one && | ||||
| 		check_bookmark hgrepo bad_bmark2 one && | ||||
| 		check_bookmark hgrepo new_bmark | ||||
| 		check_bookmark hgrepo new_bmark && | ||||
| 		check gitrepo origin/master one | ||||
| 	fi | ||||
| ' | ||||
| 
 | ||||
| @@ -734,12 +775,21 @@ test_expect_success 'remote big push non fast forward' ' | ||||
| 	echo five > content && | ||||
| 	git commit -q -a -m five && | ||||
| 
 | ||||
| 	check_push 1 --all <<-\EOF && | ||||
| 	master | ||||
| 	good_bmark | ||||
| 	bad_bmark:non-fast-forward | ||||
| 	branches/bad_branch:non-fast-forward | ||||
| 	EOF | ||||
| 	if test "$CAPABILITY_PUSH" = "t" | ||||
| 	then | ||||
| 		check_push 1 --all <<-\EOF | ||||
| 		master | ||||
| 		good_bmark | ||||
| 		bad_bmark:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	else | ||||
| 		# cap export now only report error cases | ||||
| 		check_push 1 --all <<-\EOF | ||||
| 		bad_bmark:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	fi && | ||||
| 
 | ||||
| 	git fetch && | ||||
| 
 | ||||
| @@ -753,9 +803,8 @@ test_expect_success 'remote big push non fast forward' ' | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	else | ||||
| 		# cap export now only report error cases | ||||
| 		check_push 1 --all <<-\EOF | ||||
| 		master | ||||
| 		good_bmark | ||||
| 		bad_bmark:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| @@ -797,6 +846,7 @@ test_expect_success 'remote big push force' ' | ||||
| 	fi | ||||
| 	) && | ||||
| 
 | ||||
| 	check gitrepo origin/master two && | ||||
| 	check_branch hgrepo good_branch eight && | ||||
| 	check_branch hgrepo bad_branch nine && | ||||
| 	check_branch hgrepo new_branch ten && | ||||
| @@ -814,16 +864,27 @@ test_expect_success 'remote big push dry-run' ' | ||||
| 	( | ||||
| 	cd gitrepo && | ||||
| 
 | ||||
| 	check_push 1 --dry-run --all <<-\EOF && | ||||
| 	master | ||||
| 	good_bmark | ||||
| 	branches/good_branch | ||||
| 	new_bmark:new | ||||
| 	branches/new_branch:new | ||||
| 	bad_bmark1:non-fast-forward | ||||
| 	bad_bmark2:non-fast-forward | ||||
| 	branches/bad_branch:non-fast-forward | ||||
| 	EOF | ||||
| 	if test "$CAPABILITY_PUSH" = "t" | ||||
| 	then | ||||
| 		# cap push handles refs one by one | ||||
| 		# so it will still correctly report several ok | ||||
| 		check_push 1 --dry-run --all <<-\EOF | ||||
| 		master | ||||
| 		good_bmark | ||||
| 		branches/good_branch | ||||
| 		new_bmark:new | ||||
| 		branches/new_branch:new | ||||
| 		bad_bmark1:non-fast-forward | ||||
| 		bad_bmark2:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	else | ||||
| 		check_push 1 --dry-run --all <<-\EOF | ||||
| 		bad_bmark1:non-fast-forward | ||||
| 		bad_bmark2:non-fast-forward | ||||
| 		branches/bad_branch:non-fast-forward | ||||
| 		EOF | ||||
| 	fi && | ||||
| 
 | ||||
| 	check_push 0 --dry-run master good_bmark new_bmark branches/good_branch branches/new_branch <<-\EOF | ||||
| 	master | ||||
| @@ -834,6 +895,7 @@ test_expect_success 'remote big push dry-run' ' | ||||
| 	EOF | ||||
| 	) && | ||||
| 
 | ||||
| 	check gitrepo origin/master one && | ||||
| 	check_branch hgrepo default one && | ||||
| 	check_branch hgrepo good_branch "good branch" && | ||||
| 	check_branch hgrepo bad_branch "bad branch" && | ||||
| @@ -878,6 +940,7 @@ test_expect_success 'remote big push force dry-run' ' | ||||
| 	fi | ||||
| 	) && | ||||
| 
 | ||||
| 	check gitrepo origin/master one && | ||||
| 	check_branch hgrepo default one && | ||||
| 	check_branch hgrepo good_branch "good branch" && | ||||
| 	check_branch hgrepo bad_branch "bad branch" && | ||||
| @@ -1,8 +1,9 @@ | ||||
| #!/bin/sh | ||||
| # Sharness test framework. | ||||
| # | ||||
| # Copyright (c) 2011-2012 Mathias Lafeldt | ||||
| # Copyright (c) 2005-2012 Git project | ||||
| # Copyright (c) 2005-2012 Junio C Hamano | ||||
| # Copyright (c) 2019-2023 Felipe Contreras | ||||
| # | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| @@ -17,42 +18,52 @@ | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see http://www.gnu.org/licenses/ . | ||||
| 
 | ||||
| if test -n "${ZSH_VERSION-}" | ||||
| then | ||||
| 	# shellcheck disable=SC2296 | ||||
| 	SHARNESS_SOURCE=${(%):-%x} | ||||
| 	emulate sh -o POSIX_ARGZERO | ||||
| else | ||||
| 	# shellcheck disable=SC3028 | ||||
| 	SHARNESS_SOURCE=${BASH_SOURCE-$0} | ||||
| fi | ||||
| 
 | ||||
| # Public: Current version of Sharness. | ||||
| SHARNESS_VERSION="1.1.0" | ||||
| SHARNESS_VERSION="1.2.1" | ||||
| export SHARNESS_VERSION | ||||
| 
 | ||||
| # Public: The file extension for tests.  By default, it is set to "t". | ||||
| : "${SHARNESS_TEST_EXTENSION:=t}" | ||||
| # Public: The file extension for tests.  By default, it is set to "t". | ||||
| export SHARNESS_TEST_EXTENSION | ||||
| 
 | ||||
| : "${SHARNESS_TEST_DIRECTORY:=$(dirname "$0")}" | ||||
| # ensure that SHARNESS_TEST_DIRECTORY is an absolute path so that it | ||||
| # is valid even if the current working directory is changed | ||||
| SHARNESS_TEST_DIRECTORY=$(cd "$SHARNESS_TEST_DIRECTORY" && pwd) || exit 1 | ||||
| # Public: Root directory containing tests. Tests can override this variable, | ||||
| # e.g. for testing Sharness itself. | ||||
| if test -z "$SHARNESS_TEST_DIRECTORY" | ||||
| then | ||||
| 	SHARNESS_TEST_DIRECTORY=$(pwd) | ||||
| else | ||||
| 	# ensure that SHARNESS_TEST_DIRECTORY is an absolute path so that it | ||||
| 	# is valid even if the current working directory is changed | ||||
| 	SHARNESS_TEST_DIRECTORY=$(cd "$SHARNESS_TEST_DIRECTORY" && pwd) || exit 1 | ||||
| fi | ||||
| export SHARNESS_TEST_DIRECTORY | ||||
| 
 | ||||
| if test -z "$SHARNESS_TEST_OUTPUT_DIRECTORY" | ||||
| then | ||||
| 	# Similarly, override this to store the test-results subdir | ||||
| 	# elsewhere | ||||
| 	SHARNESS_TEST_OUTPUT_DIRECTORY=$SHARNESS_TEST_DIRECTORY | ||||
| fi | ||||
| : "${SHARNESS_TEST_SRCDIR:=$(cd "$(dirname "$SHARNESS_SOURCE")" && pwd)}" | ||||
| # Public: Source directory of test code and sharness library. | ||||
| # This directory may be different from the directory in which tests are | ||||
| # being run. | ||||
| export SHARNESS_TEST_SRCDIR | ||||
| 
 | ||||
| : "${SHARNESS_TEST_OUTDIR:=$SHARNESS_TEST_DIRECTORY}" | ||||
| # Public: Directory where the output of the tests should be stored (i.e. | ||||
| # trash directories). | ||||
| export SHARNESS_TEST_OUTDIR | ||||
| 
 | ||||
| #  Reset TERM to original terminal if found, otherwise save original TERM | ||||
| [ "x" = "x$SHARNESS_ORIG_TERM" ] && | ||||
| [ -z "$SHARNESS_ORIG_TERM" ] && | ||||
| 		SHARNESS_ORIG_TERM="$TERM" || | ||||
| 		TERM="$SHARNESS_ORIG_TERM" | ||||
| # Public: The unsanitized TERM under which sharness is originally run | ||||
| export SHARNESS_ORIG_TERM | ||||
| 
 | ||||
| # Export SHELL_PATH | ||||
| : "${SHELL_PATH:=$SHELL}" | ||||
| : "${SHELL_PATH:=/bin/sh}" | ||||
| export SHELL_PATH | ||||
| 
 | ||||
| # if --tee was passed, write the output not only to the terminal, but | ||||
| @@ -62,8 +73,8 @@ done,*) | ||||
| 	# do not redirect again | ||||
| 	;; | ||||
| *' --tee '*|*' --verbose-log '*) | ||||
| 	mkdir -p "$SHARNESS_TEST_OUTPUT_DIRECTORY/test-results" | ||||
| 	BASE="$SHARNESS_TEST_OUTPUT_DIRECTORY/test-results/$(basename "$0" ".$SHARNESS_TEST_EXTENSION")" | ||||
| 	mkdir -p "$SHARNESS_TEST_OUTDIR/test-results" | ||||
| 	BASE="$SHARNESS_TEST_OUTDIR/test-results/$(basename "$0" ".$SHARNESS_TEST_EXTENSION")" | ||||
| 
 | ||||
| 	# Make this filename available to the sub-process in case it is using | ||||
| 	# --verbose-log. | ||||
| @@ -128,6 +139,9 @@ while test "$#" -ne 0; do | ||||
| 	--root=*) | ||||
| 		root=$(expr "z$1" : 'z[^=]*=\(.*\)') | ||||
| 		shift ;; | ||||
| 	-x) | ||||
| 		trace=t | ||||
| 		shift ;; | ||||
| 	--verbose-log) | ||||
| 		verbose_log=t | ||||
| 		shift ;; | ||||
| @@ -177,6 +191,40 @@ else | ||||
| 	} | ||||
| fi | ||||
| 
 | ||||
| : "${test_untraceable:=}" | ||||
| # Public: When set to a non-empty value, the current test will not be | ||||
| # traced, unless it's run with a Bash version supporting | ||||
| # BASH_XTRACEFD, i.e. v4.1 or later. | ||||
| export test_untraceable | ||||
| 
 | ||||
| if test -n "$trace" && test -n "$test_untraceable" | ||||
| then | ||||
| 	# '-x' tracing requested, but this test script can't be reliably | ||||
| 	# traced, unless it is run with a Bash version supporting | ||||
| 	# BASH_XTRACEFD (introduced in Bash v4.1). | ||||
| 	# | ||||
| 	# Perform this version check _after_ the test script was | ||||
| 	# potentially re-executed with $TEST_SHELL_PATH for '--tee' or | ||||
| 	# '--verbose-log', so the right shell is checked and the | ||||
| 	# warning is issued only once. | ||||
| 	if test -n "$BASH_VERSION" && eval ' | ||||
| 	     test ${BASH_VERSINFO[0]} -gt 4 || { | ||||
| 	       test ${BASH_VERSINFO[0]} -eq 4 && | ||||
| 	       test ${BASH_VERSINFO[1]} -ge 1 | ||||
| 	     } | ||||
| 	   ' | ||||
| 	then | ||||
| 		: Executed by a Bash version supporting BASH_XTRACEFD.  Good. | ||||
| 	else | ||||
| 		echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD" | ||||
| 		trace= | ||||
| 	fi | ||||
| fi | ||||
| if test -n "$trace" && test -z "$verbose_log" | ||||
| then | ||||
| 	verbose=t | ||||
| fi | ||||
| 
 | ||||
| TERM=dumb | ||||
| export TERM | ||||
| 
 | ||||
| @@ -209,11 +257,22 @@ else | ||||
| 	exec 4>/dev/null 3>/dev/null | ||||
| fi | ||||
| 
 | ||||
| test_failure=0 | ||||
| test_count=0 | ||||
| test_fixed=0 | ||||
| test_broken=0 | ||||
| test_success=0 | ||||
| # Send any "-x" output directly to stderr to avoid polluting tests | ||||
| # which capture stderr. We can do this unconditionally since it | ||||
| # has no effect if tracing isn't turned on. | ||||
| # | ||||
| # Note that this sets up the trace fd as soon as we assign the variable, so it | ||||
| # must come after the creation of descriptor 4 above. Likewise, we must never | ||||
| # unset this, as it has the side effect of closing descriptor 4, which we | ||||
| # use to show verbose tests to the user. | ||||
| # | ||||
| # Note also that we don't need or want to export it. The tracing is local to | ||||
| # this shell, and we would not want to influence any shells we exec. | ||||
| BASH_XTRACEFD=4 | ||||
| 
 | ||||
| # Public: The current test number, starting at 0. | ||||
| SHARNESS_TEST_NB=0 | ||||
| export SHARNESS_TEST_NB | ||||
| 
 | ||||
| die() { | ||||
| 	code=$? | ||||
| @@ -228,105 +287,30 @@ die() { | ||||
| EXIT_OK= | ||||
| trap 'die' EXIT | ||||
| 
 | ||||
| # Public: Define that a test prerequisite is available. | ||||
| # | ||||
| # The prerequisite can later be checked explicitly using test_have_prereq or | ||||
| # implicitly by specifying the prerequisite name in calls to test_expect_success | ||||
| # or test_expect_failure. | ||||
| # | ||||
| # $1 - Name of prerequisite (a simple word, in all capital letters by convention) | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   # Set PYTHON prerequisite if interpreter is available. | ||||
| #   command -v python >/dev/null && test_set_prereq PYTHON | ||||
| # | ||||
| #   # Set prerequisite depending on some variable. | ||||
| #   test -z "$NO_GETTEXT" && test_set_prereq GETTEXT | ||||
| # | ||||
| # Returns nothing. | ||||
| test_set_prereq() { | ||||
| 	satisfied_prereq="$satisfied_prereq$1 " | ||||
| } | ||||
| satisfied_prereq=" " | ||||
| test_prereq= | ||||
| missing_prereq= | ||||
| 
 | ||||
| # Public: Check if one or more test prerequisites are defined. | ||||
| # | ||||
| # The prerequisites must have previously been set with test_set_prereq. | ||||
| # The most common use of this is to skip all the tests if some essential | ||||
| # prerequisite is missing. | ||||
| # | ||||
| # $1 - Comma-separated list of test prerequisites. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   # Skip all remaining tests if prerequisite is not set. | ||||
| #   if ! test_have_prereq PERL; then | ||||
| #       skip_all='skipping perl interface tests, perl not available' | ||||
| #       test_done | ||||
| #   fi | ||||
| # | ||||
| # Returns 0 if all prerequisites are defined or 1 otherwise. | ||||
| test_have_prereq() { | ||||
| 	# prerequisites can be concatenated with ',' | ||||
| 	save_IFS=$IFS | ||||
| 	IFS=, | ||||
| 	set -- $@ | ||||
| 	IFS=$save_IFS | ||||
| test_failure=0 | ||||
| test_fixed=0 | ||||
| test_broken=0 | ||||
| test_success=0 | ||||
| 
 | ||||
| 	total_prereq=0 | ||||
| 	ok_prereq=0 | ||||
| 	missing_prereq= | ||||
| 
 | ||||
| 	for prerequisite; do | ||||
| 		case "$prerequisite" in | ||||
| 		!*) | ||||
| 			negative_prereq=t | ||||
| 			prerequisite=${prerequisite#!} | ||||
| 			;; | ||||
| 		*) | ||||
| 			negative_prereq= | ||||
| 		esac | ||||
| 
 | ||||
| 		total_prereq=$((total_prereq + 1)) | ||||
| 		case "$satisfied_prereq" in | ||||
| 		*" $prerequisite "*) | ||||
| 			satisfied_this_prereq=t | ||||
| 			;; | ||||
| 		*) | ||||
| 			satisfied_this_prereq= | ||||
| 		esac | ||||
| 
 | ||||
| 		case "$satisfied_this_prereq,$negative_prereq" in | ||||
| 		t,|,t) | ||||
| 			ok_prereq=$((ok_prereq + 1)) | ||||
| 			;; | ||||
| 		*) | ||||
| 			# Keep a list of missing prerequisites; restore | ||||
| 			# the negative marker if necessary. | ||||
| 			prerequisite=${negative_prereq:+!}$prerequisite | ||||
| 			if test -z "$missing_prereq"; then | ||||
| 				missing_prereq=$prerequisite | ||||
| 			else | ||||
| 				missing_prereq="$prerequisite,$missing_prereq" | ||||
| 			fi | ||||
| 		esac | ||||
| 	done | ||||
| 
 | ||||
| 	test $total_prereq = $ok_prereq | ||||
| } | ||||
| if test -e "$SHARNESS_TEST_SRCDIR/lib-sharness/functions.sh" | ||||
| then | ||||
| 	. "$SHARNESS_TEST_SRCDIR/lib-sharness/functions.sh" | ||||
| fi | ||||
| 
 | ||||
| # You are not expected to call test_ok_ and test_failure_ directly, use | ||||
| # the text_expect_* functions instead. | ||||
| 
 | ||||
| test_ok_() { | ||||
| 	test_success=$((test_success + 1)) | ||||
| 	say_color "" "ok $test_count - $*" | ||||
| 	say_color "" "ok $SHARNESS_TEST_NB - $*" | ||||
| } | ||||
| 
 | ||||
| test_failure_() { | ||||
| 	test_failure=$((test_failure + 1)) | ||||
| 	say_color error "not ok $test_count - $1" | ||||
| 	say_color error "not ok $SHARNESS_TEST_NB - $1" | ||||
| 	shift | ||||
| 	echo "$@" | sed -e 's/^/#	/' | ||||
| 	test "$immediate" = "" || { EXIT_OK=t; exit 1; } | ||||
| @@ -334,53 +318,76 @@ test_failure_() { | ||||
| 
 | ||||
| test_known_broken_ok_() { | ||||
| 	test_fixed=$((test_fixed + 1)) | ||||
| 	say_color error "ok $test_count - $* # TODO known breakage vanished" | ||||
| 	say_color error "ok $SHARNESS_TEST_NB - $* # TODO known breakage vanished" | ||||
| } | ||||
| 
 | ||||
| test_known_broken_failure_() { | ||||
| 	test_broken=$((test_broken + 1)) | ||||
| 	say_color warn "not ok $test_count - $* # TODO known breakage" | ||||
| 	say_color warn "not ok $SHARNESS_TEST_NB - $* # TODO known breakage" | ||||
| } | ||||
| 
 | ||||
| # Public: Execute commands in debug mode. | ||||
| # | ||||
| # Takes a single argument and evaluates it only when the test script is started | ||||
| # with --debug. This is primarily meant for use during the development of test | ||||
| # scripts. | ||||
| # | ||||
| # $1 - Commands to be executed. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_debug "cat some_log_file" | ||||
| # | ||||
| # Returns the exit code of the last command executed in debug mode or 0 | ||||
| #   otherwise. | ||||
| test_debug() { | ||||
| 	test "$debug" = "" || eval "$1" | ||||
| want_trace () { | ||||
| 	test "$trace" = t && { | ||||
| 		test "$verbose" = t || test "$verbose_log" = t | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| # Public: Stop execution and start a shell. | ||||
| # | ||||
| # This is useful for debugging tests and only makes sense together with "-v". | ||||
| # Be sure to remove all invocations of this command before submitting. | ||||
| test_pause() { | ||||
| 	if test "$verbose" = t; then | ||||
| 		"$SHELL_PATH" <&6 >&3 2>&4 | ||||
| 	else | ||||
| 		error >&5 "test_pause requires --verbose" | ||||
| # This is a separate function because some tests use | ||||
| # "return" to end a test_expect_success block early | ||||
| # (and we want to make sure we run any cleanup like | ||||
| # "set +x"). | ||||
| test_eval_inner_ () { | ||||
| 	# Do not add anything extra (including LF) after '$*' | ||||
| 	eval " | ||||
| 		want_trace && set -x | ||||
| 		$*" | ||||
| } | ||||
| 
 | ||||
| test_eval_x_ () { | ||||
| 	# If "-x" tracing is in effect, then we want to avoid polluting stderr | ||||
| 	# with non-test commands. But once in "set -x" mode, we cannot prevent | ||||
| 	# the shell from printing the "set +x" to turn it off (nor the saving | ||||
| 	# of $? before that). But we can make sure that the output goes to | ||||
| 	# /dev/null. | ||||
| 	# | ||||
| 	# There are a few subtleties here: | ||||
| 	# | ||||
| 	#   - we have to redirect descriptor 4 in addition to 2, to cover | ||||
| 	#     BASH_XTRACEFD | ||||
| 	# | ||||
| 	#   - the actual eval has to come before the redirection block (since | ||||
| 	#     it needs to see descriptor 4 to set up its stderr) | ||||
| 	# | ||||
| 	#   - likewise, any error message we print must be outside the block to | ||||
| 	#     access descriptor 4 | ||||
| 	# | ||||
| 	#   - checking $? has to come immediately after the eval, but it must | ||||
| 	#     be _inside_ the block to avoid polluting the "set -x" output | ||||
| 	# | ||||
| 
 | ||||
| 	test_eval_inner_ "$@" </dev/null >&3 2>&4 | ||||
| 	{ | ||||
| 		test_eval_ret_=$? | ||||
| 		if want_trace | ||||
| 		then | ||||
| 			set +x | ||||
| 		fi | ||||
| 	} 2>/dev/null 4>&2 | ||||
| 
 | ||||
| 	if test "$test_eval_ret_" != 0 && want_trace | ||||
| 	then | ||||
| 		say_color error >&4 "error: last command exited with \$?=$test_eval_ret_" | ||||
| 	fi | ||||
| 	return $test_eval_ret_ | ||||
| } | ||||
| 
 | ||||
| test_eval_() { | ||||
| 	# This is a separate function because some tests use | ||||
| 	# "return" to end a test_expect_success block early. | ||||
| 	case ",$test_prereq," in | ||||
| 	*,INTERACTIVE,*) | ||||
| 		eval "$*" | ||||
| 		;; | ||||
| 	*) | ||||
| 		eval </dev/null >&3 2>&4 "$*" | ||||
| 		test_eval_x_ "$@" | ||||
| 		;; | ||||
| 	esac | ||||
| } | ||||
| @@ -392,13 +399,22 @@ test_run_() { | ||||
| 	eval_ret=$? | ||||
| 
 | ||||
| 	if test "$chain_lint" = "t"; then | ||||
| 		# turn off tracing for this test-eval, as it simply creates | ||||
| 		# confusing noise in the "-x" output | ||||
| 		trace_tmp=$trace | ||||
| 		trace= | ||||
| 		# 117 is magic because it is unlikely to match the exit | ||||
| 		# code of other programs | ||||
| 		test_eval_ "(exit 117) && $1" | ||||
| 		if test "$?" != 117; then | ||||
| 			error "bug in the test script: broken &&-chain: $1" | ||||
| 		fi | ||||
| 		trace=$trace_tmp | ||||
| 	fi | ||||
| 
 | ||||
| 	if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"; then | ||||
| 	if test -z "$immediate" || test $eval_ret = 0 || | ||||
| 	   test -n "$expecting_failure" && test "$test_cleanup" != ":" | ||||
| 	then | ||||
| 		test_eval_ "$test_cleanup" | ||||
| 	fi | ||||
| 	if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then | ||||
| @@ -408,10 +424,11 @@ test_run_() { | ||||
| } | ||||
| 
 | ||||
| test_skip_() { | ||||
| 	test_count=$((test_count + 1)) | ||||
| 	SHARNESS_TEST_NB=$((SHARNESS_TEST_NB + 1)) | ||||
| 	to_skip= | ||||
| 	for skp in $SKIP_TESTS; do | ||||
| 		case $this_test.$test_count in | ||||
| 		# shellcheck disable=SC2254 | ||||
| 		case $this_test.$SHARNESS_TEST_NB in | ||||
| 		$skp) | ||||
| 			to_skip=t | ||||
| 			break | ||||
| @@ -428,7 +445,7 @@ test_skip_() { | ||||
| 		fi | ||||
| 
 | ||||
| 		say_color skip >&3 "skipping test: $*" | ||||
| 		say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})" | ||||
| 		say_color skip "ok $SHARNESS_TEST_NB # skip $1 (missing $missing_prereq${of_prereq})" | ||||
| 		: true | ||||
| 		;; | ||||
| 	*) | ||||
| @@ -437,6 +454,13 @@ test_skip_() { | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| remove_trash_() { | ||||
| 	test -d "$remove_trash" && ( | ||||
| 		cd "$(dirname "$remove_trash")" && | ||||
| 			rm -rf "$(basename "$remove_trash")" | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| # Public: Run test commands and expect them to succeed. | ||||
| # | ||||
| # When the test passed, an "ok" message is printed and the number of successful | ||||
| @@ -563,246 +587,6 @@ test_expect_unstable() { | ||||
| 	echo >&3 "" | ||||
| } | ||||
| 
 | ||||
| # Public: Run command and ensure that it fails in a controlled way. | ||||
| # | ||||
| # Use it instead of "! <command>". For example, when <command> dies due to a | ||||
| # segfault, test_must_fail diagnoses it as an error, while "! <command>" would | ||||
| # mistakenly be treated as just another expected failure. | ||||
| # | ||||
| # This is one of the prefix functions to be used inside test_expect_success or | ||||
| # test_expect_failure. | ||||
| # | ||||
| # $1.. - Command to be executed. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_expect_success 'complain and die' ' | ||||
| #       do something && | ||||
| #       do something else && | ||||
| #       test_must_fail git checkout ../outerspace | ||||
| #   ' | ||||
| # | ||||
| # Returns 1 if the command succeeded (exit code 0). | ||||
| # Returns 1 if the command died by signal (exit codes 130-192) | ||||
| # Returns 1 if the command could not be found (exit code 127). | ||||
| # Returns 0 otherwise. | ||||
| test_must_fail() { | ||||
| 	"$@" | ||||
| 	exit_code=$? | ||||
| 	if test $exit_code = 0; then | ||||
| 		echo >&2 "test_must_fail: command succeeded: $*" | ||||
| 		return 1 | ||||
| 	elif test $exit_code -gt 129 -a $exit_code -le 192; then | ||||
| 		echo >&2 "test_must_fail: died by signal: $*" | ||||
| 		return 1 | ||||
| 	elif test $exit_code = 127; then | ||||
| 		echo >&2 "test_must_fail: command not found: $*" | ||||
| 		return 1 | ||||
| 	fi | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| # Public: Run command and ensure that it succeeds or fails in a controlled way. | ||||
| # | ||||
| # Similar to test_must_fail, but tolerates success too. Use it instead of | ||||
| # "<command> || :" to catch failures caused by a segfault, for instance. | ||||
| # | ||||
| # This is one of the prefix functions to be used inside test_expect_success or | ||||
| # test_expect_failure. | ||||
| # | ||||
| # $1.. - Command to be executed. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_expect_success 'some command works without configuration' ' | ||||
| #       test_might_fail git config --unset all.configuration && | ||||
| #       do something | ||||
| #   ' | ||||
| # | ||||
| # Returns 1 if the command died by signal (exit codes 130-192) | ||||
| # Returns 1 if the command could not be found (exit code 127). | ||||
| # Returns 0 otherwise. | ||||
| test_might_fail() { | ||||
| 	"$@" | ||||
| 	exit_code=$? | ||||
| 	if test $exit_code -gt 129 -a $exit_code -le 192; then | ||||
| 		echo >&2 "test_might_fail: died by signal: $*" | ||||
| 		return 1 | ||||
| 	elif test $exit_code = 127; then | ||||
| 		echo >&2 "test_might_fail: command not found: $*" | ||||
| 		return 1 | ||||
| 	fi | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| # Public: Run command and ensure it exits with a given exit code. | ||||
| # | ||||
| # This is one of the prefix functions to be used inside test_expect_success or | ||||
| # test_expect_failure. | ||||
| # | ||||
| # $1   - Expected exit code. | ||||
| # $2.. - Command to be executed. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_expect_success 'Merge with d/f conflicts' ' | ||||
| #       test_expect_code 1 git merge "merge msg" B master | ||||
| #   ' | ||||
| # | ||||
| # Returns 0 if the expected exit code is returned or 1 otherwise. | ||||
| test_expect_code() { | ||||
| 	want_code=$1 | ||||
| 	shift | ||||
| 	"$@" | ||||
| 	exit_code=$? | ||||
| 	if test "$exit_code" = "$want_code"; then | ||||
| 		return 0 | ||||
| 	fi | ||||
| 
 | ||||
| 	echo >&2 "test_expect_code: command exited with $exit_code, we wanted $want_code $*" | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| # Public: Compare two files to see if expected output matches actual output. | ||||
| # | ||||
| # The TEST_CMP variable defines the command used for the comparison; it | ||||
| # defaults to "diff -u". Only when the test script was started with --verbose, | ||||
| # will the command's output, the diff, be printed to the standard output. | ||||
| # | ||||
| # This is one of the prefix functions to be used inside test_expect_success or | ||||
| # test_expect_failure. | ||||
| # | ||||
| # $1 - Path to file with expected output. | ||||
| # $2 - Path to file with actual output. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_expect_success 'foo works' ' | ||||
| #       echo expected >expected && | ||||
| #       foo >actual && | ||||
| #       test_cmp expected actual | ||||
| #   ' | ||||
| # | ||||
| # Returns the exit code of the command set by TEST_CMP. | ||||
| test_cmp() { | ||||
| 	${TEST_CMP:-diff -u} "$@" | ||||
| } | ||||
| 
 | ||||
| # Public: portably print a sequence of numbers. | ||||
| # | ||||
| # seq is not in POSIX and GNU seq might not be available everywhere, | ||||
| # so it is nice to have a seq implementation, even a very simple one. | ||||
| # | ||||
| # $1 - Starting number. | ||||
| # $2 - Ending number. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_expect_success 'foo works 10 times' ' | ||||
| #       for i in $(test_seq 1 10) | ||||
| #       do | ||||
| #           foo || return | ||||
| #       done | ||||
| #   ' | ||||
| # | ||||
| # Returns 0 if all the specified numbers can be displayed. | ||||
| test_seq() { | ||||
| 	i="$1" | ||||
| 	j="$2" | ||||
| 	while test "$i" -le "$j" | ||||
| 	do | ||||
| 		echo "$i" || return | ||||
| 		i=$(("$i" + 1)) | ||||
| 	done | ||||
| } | ||||
| 
 | ||||
| # Public: Check if the file expected to be empty is indeed empty, and barfs | ||||
| # otherwise. | ||||
| # | ||||
| # $1 - File to check for emptiness. | ||||
| # | ||||
| # Returns 0 if file is empty, 1 otherwise. | ||||
| test_must_be_empty() { | ||||
| 	if test -s "$1" | ||||
| 	then | ||||
| 		echo "'$1' is not empty, it contains:" | ||||
| 		cat "$1" | ||||
| 		return 1 | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| # debugging-friendly alternatives to "test [-f|-d|-e]" | ||||
| # The commands test the existence or non-existence of $1. $2 can be | ||||
| # given to provide a more precise diagnosis. | ||||
| test_path_is_file () { | ||||
| 	if ! test -f "$1" | ||||
| 	then | ||||
| 		echo "File $1 doesn't exist. $2" | ||||
| 		false | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| test_path_is_dir () { | ||||
| 	if ! test -d "$1" | ||||
| 	then | ||||
| 		echo "Directory $1 doesn't exist. $2" | ||||
| 		false | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| # Check if the directory exists and is empty as expected, barf otherwise. | ||||
| test_dir_is_empty () { | ||||
| 	test_path_is_dir "$1" && | ||||
| 	if test -n "$(find "$1" -mindepth 1 -maxdepth 1)" | ||||
| 	then | ||||
| 		echo "Directory '$1' is not empty, it contains:" | ||||
| 		ls -la "$1" | ||||
| 		return 1 | ||||
| 	fi | ||||
| } | ||||
| 
 | ||||
| # Public: Schedule cleanup commands to be run unconditionally at the end of a | ||||
| # test. | ||||
| # | ||||
| # If some cleanup command fails, the test will not pass. With --immediate, no | ||||
| # cleanup is done to help diagnose what went wrong. | ||||
| # | ||||
| # This is one of the prefix functions to be used inside test_expect_success or | ||||
| # test_expect_failure. | ||||
| # | ||||
| # $1.. - Commands to prepend to the list of cleanup commands. | ||||
| # | ||||
| # Examples | ||||
| # | ||||
| #   test_expect_success 'test core.capslock' ' | ||||
| #       git config core.capslock true && | ||||
| #       test_when_finished "git config --unset core.capslock" && | ||||
| #       do_something | ||||
| #   ' | ||||
| # | ||||
| # Returns the exit code of the last cleanup command executed. | ||||
| test_when_finished() { | ||||
| 	test_cleanup="{ $* | ||||
| 		} && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" | ||||
| } | ||||
| 
 | ||||
| # Public: Schedule cleanup commands to be run unconditionally when all tests | ||||
| # have run. | ||||
| # | ||||
| # This can be used to clean up things like test databases. It is not needed to | ||||
| # clean up temporary files, as test_done already does that. | ||||
| # | ||||
| # Examples: | ||||
| # | ||||
| #   cleanup mysql -e "DROP DATABASE mytest" | ||||
| # | ||||
| # Returns the exit code of the last cleanup command executed. | ||||
| final_cleanup= | ||||
| cleanup() { | ||||
| 	final_cleanup="{ $* | ||||
| 		} && (exit \"\$eval_ret\"); eval_ret=\$?; $final_cleanup" | ||||
| } | ||||
| 
 | ||||
| # Public: Summarize test results and exit with an appropriate error code. | ||||
| # | ||||
| # Must be called at the end of each test script. | ||||
| @@ -823,16 +607,17 @@ cleanup() { | ||||
| #   fi | ||||
| # | ||||
| # Returns 0 if all tests passed or 1 if there was a failure. | ||||
| # shellcheck disable=SC2154,SC2034 | ||||
| test_done() { | ||||
| 	EXIT_OK=t | ||||
| 
 | ||||
| 	if test -z "$HARNESS_ACTIVE"; then | ||||
| 		test_results_dir="$SHARNESS_TEST_OUTPUT_DIRECTORY/test-results" | ||||
| 		test_results_dir="$SHARNESS_TEST_OUTDIR/test-results" | ||||
| 		mkdir -p "$test_results_dir" | ||||
| 		test_results_path="$test_results_dir/$this_test.$$.counts" | ||||
| 
 | ||||
| 		cat >>"$test_results_path" <<-EOF | ||||
| 		total $test_count | ||||
| 		total $SHARNESS_TEST_NB | ||||
| 		success $test_success | ||||
| 		fixed $test_fixed | ||||
| 		broken $test_broken | ||||
| @@ -848,54 +633,43 @@ test_done() { | ||||
| 		say_color warn "# still have $test_broken known breakage(s)" | ||||
| 	fi | ||||
| 	if test "$test_broken" != 0 || test "$test_fixed" != 0; then | ||||
| 		test_remaining=$((test_count - test_broken - test_fixed)) | ||||
| 		test_remaining=$((SHARNESS_TEST_NB - test_broken - test_fixed)) | ||||
| 		msg="remaining $test_remaining test(s)" | ||||
| 	else | ||||
| 		test_remaining=$test_count | ||||
| 		msg="$test_count test(s)" | ||||
| 		test_remaining=$SHARNESS_TEST_NB | ||||
| 		msg="$SHARNESS_TEST_NB test(s)" | ||||
| 	fi | ||||
| 
 | ||||
| 	case "$test_failure" in | ||||
| 	0) | ||||
| 		# Maybe print SKIP message | ||||
| 		if test -n "$skip_all" && test $test_count -gt 0; then | ||||
| 			error "Can't use skip_all after running some tests" | ||||
| 		fi | ||||
| 		[ -z "$skip_all" ] || skip_all=" # SKIP $skip_all" | ||||
| 
 | ||||
| 		if test $test_remaining -gt 0; then | ||||
| 		check_skip_all_ | ||||
| 		if test "$test_remaining" -gt 0; then | ||||
| 			say_color pass "# passed all $msg" | ||||
| 		fi | ||||
| 		say "1..$test_count$skip_all" | ||||
| 		say "1..$SHARNESS_TEST_NB$skip_all" | ||||
| 
 | ||||
| 		test_eval_ "$final_cleanup" | ||||
| 
 | ||||
| 		test -d "$remove_trash" && | ||||
| 		cd "$(dirname "$remove_trash")" && | ||||
| 		rm -rf "$(basename "$remove_trash")" | ||||
| 		remove_trash_ | ||||
| 
 | ||||
| 		exit 0 ;; | ||||
| 
 | ||||
| 	*) | ||||
| 		say_color error "# failed $test_failure among $msg" | ||||
| 		say "1..$test_count" | ||||
| 		say "1..$SHARNESS_TEST_NB" | ||||
| 
 | ||||
| 		exit 1 ;; | ||||
| 
 | ||||
| 	esac | ||||
| } | ||||
| 
 | ||||
| # Public: Source directory of test code and sharness library. | ||||
| # This directory may be different from the directory in which tests are | ||||
| # being run. | ||||
| : "${SHARNESS_TEST_SRCDIR:=$(cd "$(dirname "$0")" && pwd)}" | ||||
| export SHARNESS_TEST_SRCDIR | ||||
| 
 | ||||
| : "${SHARNESS_BUILD_DIRECTORY:="$SHARNESS_TEST_DIRECTORY/.."}" | ||||
| # Public: Build directory that will be added to PATH. By default, it is set to | ||||
| # the parent directory of SHARNESS_TEST_DIRECTORY. | ||||
| : "${SHARNESS_BUILD_DIRECTORY:="$SHARNESS_TEST_DIRECTORY/.."}" | ||||
| export SHARNESS_BUILD_DIRECTORY | ||||
| PATH="$SHARNESS_BUILD_DIRECTORY:$PATH" | ||||
| export PATH SHARNESS_BUILD_DIRECTORY | ||||
| export PATH | ||||
| 
 | ||||
| # Public: Path to test script currently executed. | ||||
| SHARNESS_TEST_FILE="$0" | ||||
| @@ -906,7 +680,7 @@ SHARNESS_TRASH_DIRECTORY="trash directory.$(basename "$SHARNESS_TEST_FILE" ".$SH | ||||
| test -n "$root" && SHARNESS_TRASH_DIRECTORY="$root/$SHARNESS_TRASH_DIRECTORY" | ||||
| case "$SHARNESS_TRASH_DIRECTORY" in | ||||
| /*) ;; # absolute path is good | ||||
|  *) SHARNESS_TRASH_DIRECTORY="$SHARNESS_TEST_OUTPUT_DIRECTORY/$SHARNESS_TRASH_DIRECTORY" ;; | ||||
|  *) SHARNESS_TRASH_DIRECTORY="$SHARNESS_TEST_OUTDIR/$SHARNESS_TRASH_DIRECTORY" ;; | ||||
| esac | ||||
| test "$debug" = "t" || remove_trash="$SHARNESS_TRASH_DIRECTORY" | ||||
| rm -rf "$SHARNESS_TRASH_DIRECTORY" || { | ||||
| @@ -917,11 +691,11 @@ rm -rf "$SHARNESS_TRASH_DIRECTORY" || { | ||||
| 
 | ||||
| 
 | ||||
| # | ||||
| #  Load any extensions in $srcdir/sharness.d/*.sh | ||||
| #  Load any extensions in $testdir/sharness.d/*.sh | ||||
| # | ||||
| if test -d "${SHARNESS_TEST_SRCDIR}/sharness.d" | ||||
| if test -d "${SHARNESS_TEST_DIRECTORY}/sharness.d" | ||||
| then | ||||
| 	for file in "${SHARNESS_TEST_SRCDIR}"/sharness.d/*.sh | ||||
| 	for file in "${SHARNESS_TEST_DIRECTORY}"/sharness.d/*.sh | ||||
| 	do | ||||
| 		# Ensure glob was not an empty match: | ||||
| 		test -e "${file}" || break | ||||
| @@ -930,6 +704,7 @@ then | ||||
| 		then | ||||
| 			echo >&5 "sharness: loading extensions from ${file}" | ||||
| 		fi | ||||
| 		# shellcheck disable=SC1090 | ||||
| 		. "${file}" | ||||
| 		if test $? != 0 | ||||
| 		then | ||||
| @@ -946,14 +721,28 @@ export SHARNESS_TRASH_DIRECTORY | ||||
| HOME="$SHARNESS_TRASH_DIRECTORY" | ||||
| export HOME | ||||
| 
 | ||||
| # shellcheck disable=SC3028 | ||||
| if [ "$OSTYPE" = msys ]; then | ||||
| 	USERPROFILE="$SHARNESS_TRASH_DIRECTORY" | ||||
| 	export USERPROFILE | ||||
| fi | ||||
| 
 | ||||
| mkdir -p "$SHARNESS_TRASH_DIRECTORY" || exit 1 | ||||
| # Use -P to resolve symlinks in our working directory so that the cwd | ||||
| # in subprocesses like git equals our $PWD (for pathname comparisons). | ||||
| cd -P "$SHARNESS_TRASH_DIRECTORY" || exit 1 | ||||
| 
 | ||||
| check_skip_all_() { | ||||
| 	if test -n "$skip_all" && test $SHARNESS_TEST_NB -gt 0; then | ||||
| 		error "Can't use skip_all after running some tests" | ||||
| 	fi | ||||
| 	[ -z "$skip_all" ] || skip_all=" # SKIP $skip_all" | ||||
| } | ||||
| 
 | ||||
| this_test=${SHARNESS_TEST_FILE##*/} | ||||
| this_test=${this_test%.$SHARNESS_TEST_EXTENSION} | ||||
| this_test=${this_test%".$SHARNESS_TEST_EXTENSION"} | ||||
| for skp in $SKIP_TESTS; do | ||||
| 	# shellcheck disable=SC2254 | ||||
| 	case "$this_test" in | ||||
| 	$skp) | ||||
| 		say_color info >&3 "skipping test $this_test altogether" | ||||
| @@ -1,8 +1,10 @@ | ||||
| #!/bin/sh | ||||
| #!/bin/bash | ||||
| 
 | ||||
| : "${SHARNESS_TEST_SRCDIR:=$(cd "$(dirname "${BASH_SOURCE-$0}")" && pwd)}" | ||||
| 
 | ||||
| if [ -z "$SHARNESS" ] ; then | ||||
| 	for d in \ | ||||
| 		"." \ | ||||
| 		"$SHARNESS_TEST_SRCDIR" \ | ||||
| 		"$HOME/share/sharness" \ | ||||
| 		"/usr/local/share/sharness" \ | ||||
| 		"/usr/share/sharness" | ||||
| @@ -27,6 +29,83 @@ SHARNESS_BUILD_DIRECTORY="$(mktemp -d)" | ||||
| export PATH="${PATH#*:}" | ||||
| rmdir "$SHARNESS_BUILD_DIRECTORY" | ||||
| 
 | ||||
| GIT_AUTHOR_EMAIL=author@example.com | ||||
| GIT_AUTHOR_NAME='A U Thor' | ||||
| GIT_COMMITTER_EMAIL=committer@example.com | ||||
| GIT_COMMITTER_NAME='C O Mitter' | ||||
| export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME | ||||
| export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME | ||||
| 
 | ||||
| # maintain backwards compatible default | ||||
| # (as used in remote helper) | ||||
| git config --global init.defaultBranch master | ||||
| git config --global protocol.file.allow always | ||||
| 
 | ||||
| unset XDG_CONFIG_HOME | ||||
| 
 | ||||
| test_set_prereq() { | ||||
| 	satisfied_prereq="$satisfied_prereq$1 " | ||||
| } | ||||
| satisfied_prereq=" " | ||||
| 
 | ||||
| case "$(uname -s)" in | ||||
| MSYS*|MINGW*) | ||||
| 	test_set_prereq WIN | ||||
| 	export TEST_CMP='diff --strip-trailing-cr -u' | ||||
| 	;; | ||||
| esac | ||||
| 
 | ||||
| test_cmp() { | ||||
| 	${TEST_CMP:-diff -u} "$@" | ||||
| } | ||||
| 
 | ||||
| test_when_finished() { | ||||
| 	test_cleanup="{ $* | ||||
| 		} && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" | ||||
| } | ||||
| 
 | ||||
| test_expect_code() { | ||||
| 	want_code=$1 | ||||
| 	shift | ||||
| 	"$@" | ||||
| 	exit_code=$? | ||||
| 	if test "$exit_code" = "$want_code"; then | ||||
| 		return 0 | ||||
| 	fi | ||||
| 
 | ||||
| 	echo >&2 "test_expect_code: command exited with $exit_code, we wanted $want_code $*" | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| test_have_prereq() { | ||||
| 	prerequisite=$1 | ||||
| 
 | ||||
| 	case "$prerequisite" in | ||||
| 	!*) | ||||
| 		negative_prereq=t | ||||
| 		prerequisite=${prerequisite#!} | ||||
| 		;; | ||||
| 	*) | ||||
| 		negative_prereq= | ||||
| 	esac | ||||
| 
 | ||||
| 	case "$satisfied_prereq" in | ||||
| 	*" $prerequisite "*) | ||||
| 		satisfied_this_prereq=t | ||||
| 		;; | ||||
| 	*) | ||||
| 		satisfied_this_prereq= | ||||
| 	esac | ||||
| 
 | ||||
| 	case "$satisfied_this_prereq,$negative_prereq" in | ||||
| 	t,|,t) | ||||
| 		return 0 | ||||
| 		;; | ||||
| 	esac | ||||
| 
 | ||||
| 	return 1 | ||||
| } | ||||
| 
 | ||||
| if [ -z "$TEST_INSTALLED_SCRIPTS" ] ; then | ||||
| 	if [ -n "$PYTHON" ] && "$PYTHON" -c 'import mercurial' 2> /dev/null ; then | ||||
| 		: Use chosen Python version | ||||
| @@ -55,13 +134,3 @@ else | ||||
| 	# The build/install process ensures Python is available | ||||
| 	test_set_prereq PYTHON | ||||
| fi | ||||
| 
 | ||||
| GIT_AUTHOR_EMAIL=author@example.com | ||||
| GIT_AUTHOR_NAME='A U Thor' | ||||
| GIT_COMMITTER_EMAIL=committer@example.com | ||||
| GIT_COMMITTER_NAME='C O Mitter' | ||||
| export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME | ||||
| export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME | ||||
| # maintain backwards compatible default | ||||
| # (as used in remote helper) | ||||
| git config --global init.defaultBranch master | ||||
							
								
								
									
										568
									
								
								test/hg-git.t
									
									
									
									
									
								
							
							
						
						
									
										568
									
								
								test/hg-git.t
									
									
									
									
									
								
							| @@ -1,568 +0,0 @@ | ||||
| #!/bin/sh | ||||
| # | ||||
| # Copyright (c) 2012 Felipe Contreras | ||||
| # | ||||
| # Base commands from hg-git tests: | ||||
| # https://bitbucket.org/durin42/hg-git/src | ||||
| # | ||||
|  | ||||
| test_description='Test remote-hg output compared to hg-git' | ||||
|  | ||||
| test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/ | ||||
| . "$TEST_DIRECTORY"/test-lib.sh | ||||
|  | ||||
| if ! test_have_prereq PYTHON | ||||
| then | ||||
| 	skip_all='skipping remote-hg tests; python with mercurial not available' | ||||
| 	test_done | ||||
| fi | ||||
|  | ||||
| if "$PYTHON" -c 'import hggit' > /dev/null 2>&1 | ||||
| then | ||||
| 	hggit=hggit | ||||
| elif "$PYTHON" -c 'import hgext.git' > /dev/null 2>&1 | ||||
| then | ||||
| 	hggit=hgext.git | ||||
| else | ||||
| 	skip_all='skipping remote-hg tests; hg-git not available' | ||||
| 	test_done | ||||
| fi | ||||
|  | ||||
| # clone to a git repo with git | ||||
| git_clone_git () { | ||||
| 	git clone -q "hg::$1" $2 && | ||||
| 	(cd $2 && git checkout master && git branch -D default) | ||||
| } | ||||
|  | ||||
| # clone to an hg repo with git | ||||
| hg_clone_git () { | ||||
| 	( | ||||
| 	hg init $2 && | ||||
| 	hg -R $2 bookmark -i master && | ||||
| 	cd $1 && | ||||
| 	git push -q "hg::../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' | ||||
| 	) && | ||||
|  | ||||
| 	(cd $2 && hg -q update) | ||||
| } | ||||
|  | ||||
| # clone to a git repo with hg | ||||
| git_clone_hg () { | ||||
| 	( | ||||
| 	git init -q $2 && | ||||
| 	cd $1 && | ||||
| 	hg bookmark -i -f -r tip master && | ||||
| 	hg -q push -r master ../$2 || true | ||||
| 	) | ||||
| } | ||||
|  | ||||
| # clone to an hg repo with hg | ||||
| hg_clone_hg () { | ||||
| 	hg -q clone $1 $2 | ||||
| } | ||||
|  | ||||
| # push an hg repo with git | ||||
| hg_push_git () { | ||||
| 	( | ||||
| 	cd $2 | ||||
| 	git checkout -q -b tmp && | ||||
| 	git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' && | ||||
| 	git branch -D default && | ||||
| 	git checkout -q @{-1} && | ||||
| 	git branch -q -D tmp 2> /dev/null || true | ||||
| 	) | ||||
| } | ||||
|  | ||||
| # push an hg git repo with hg | ||||
| hg_push_hg () { | ||||
| 	( | ||||
| 	cd $1 && | ||||
| 	hg -q push ../$2 || true | ||||
| 	) | ||||
| } | ||||
|  | ||||
| hg_log () { | ||||
| 	hg -R $1 log --graph --debug > log && | ||||
| 	grep -v 'tag: *default/' log | ||||
| } | ||||
|  | ||||
| git_log () { | ||||
| 	git --git-dir=$1/.git fast-export --branches | ||||
| } | ||||
|  | ||||
| setup () { | ||||
| 	cat > "$HOME"/.hgrc <<-EOF && | ||||
| 	[ui] | ||||
| 	username = A U Thor <author@example.com> | ||||
| 	[defaults] | ||||
| 	backout = -d "0 0" | ||||
| 	commit = -d "0 0" | ||||
| 	debugrawcommit = -d "0 0" | ||||
| 	tag = -d "0 0" | ||||
| 	[extensions] | ||||
| 	$hggit = | ||||
| 	graphlog = | ||||
| 	[git] | ||||
| 	debugextrainmessage = 1 | ||||
| 	EOF | ||||
| 	git config --global receive.denycurrentbranch warn | ||||
| 	git config --global remote-hg.hg-git-compat true | ||||
| 	git config --global remote-hg.track-branches false | ||||
| 	git config --global remote-hg.shared-marks false | ||||
|  | ||||
| 	HGEDITOR=true | ||||
| 	HGMERGE=true | ||||
|  | ||||
| 	GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" | ||||
| 	GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" | ||||
| 	export HGEDITOR HGMERGE GIT_AUTHOR_DATE GIT_COMMITTER_DATE | ||||
| } | ||||
|  | ||||
| setup | ||||
|  | ||||
| test_expect_success 'rename' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo alpha > alpha && | ||||
| 	hg add alpha && | ||||
| 	hg commit -m "add alpha" && | ||||
| 	hg mv alpha beta && | ||||
| 	hg commit -m "rename alpha to beta" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		git_clone_$x hgrepo1 gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
| 		hg_log hgrepo2-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'executable bit' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	echo alpha > alpha && | ||||
| 	chmod 0644 alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	chmod 0755 alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "set executable bit" && | ||||
| 	chmod 0644 alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "clear executable bit" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		( | ||||
| 		hg_clone_$x gitrepo hgrepo-$x && | ||||
| 		cd hgrepo-$x && | ||||
| 		hg_log . && | ||||
| 		hg manifest -r 1 -v && | ||||
| 		hg manifest -v | ||||
| 		) > "output-$x" && | ||||
|  | ||||
| 		git_clone_$x hgrepo-$x gitrepo2-$x && | ||||
| 		git_log gitrepo2-$x > "log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp output-hg output-git && | ||||
| 	test_cmp log-hg log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'symlink' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	ln -s alpha beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		( | ||||
| 		hg_clone_$x gitrepo hgrepo-$x && | ||||
| 		cd hgrepo-$x && | ||||
| 		hg_log . && | ||||
| 		hg manifest -v | ||||
| 		) > "output-$x" && | ||||
|  | ||||
| 		git_clone_$x hgrepo-$x gitrepo2-$x && | ||||
| 		git_log gitrepo2-$x > "log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp output-hg output-git && | ||||
| 	test_cmp log-hg log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'merge conflict 1' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo A > afile && | ||||
| 	hg add afile && | ||||
| 	hg ci -m "origin" && | ||||
|  | ||||
| 	echo B > afile && | ||||
| 	hg ci -m "A->B" && | ||||
|  | ||||
| 	hg up -r0 && | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "A->C" && | ||||
|  | ||||
| 	hg merge -r1 && | ||||
| 	echo C > afile && | ||||
| 	hg resolve -m afile && | ||||
| 	hg ci -m "merge to C" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		git_clone_$x hgrepo1 gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
| 		hg_log hgrepo2-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'merge conflict 2' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo A > afile && | ||||
| 	hg add afile && | ||||
| 	hg ci -m "origin" && | ||||
|  | ||||
| 	echo B > afile && | ||||
| 	hg ci -m "A->B" && | ||||
|  | ||||
| 	hg up -r0 && | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "A->C" && | ||||
|  | ||||
| 	hg merge -r1 || true && | ||||
| 	echo B > afile && | ||||
| 	hg resolve -m afile && | ||||
| 	hg ci -m "merge to B" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		git_clone_$x hgrepo1 gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
| 		hg_log hgrepo2-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'converged merge' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	hg init hgrepo1 && | ||||
| 	cd hgrepo1 && | ||||
| 	echo A > afile && | ||||
| 	hg add afile && | ||||
| 	hg ci -m "origin" && | ||||
|  | ||||
| 	echo B > afile && | ||||
| 	hg ci -m "A->B" && | ||||
|  | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "B->C" && | ||||
|  | ||||
| 	hg up -r0 && | ||||
| 	echo C > afile && | ||||
| 	hg ci -m "A->C" && | ||||
|  | ||||
| 	hg merge -r2 || true && | ||||
| 	hg ci -m "merge" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		git_clone_$x hgrepo1 gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
| 		hg_log hgrepo2-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'encoding' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
|  | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add älphà" && | ||||
|  | ||||
| 	GIT_AUTHOR_NAME="tést èncödîng" && | ||||
| 	export GIT_AUTHOR_NAME && | ||||
| 	echo beta > beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" && | ||||
|  | ||||
| 	echo gamma > gamma && | ||||
| 	git add gamma && | ||||
| 	git commit -m "add gämmâ" && | ||||
|  | ||||
| 	: TODO git config i18n.commitencoding latin-1 && | ||||
| 	echo delta > delta && | ||||
| 	git add delta && | ||||
| 	git commit -m "add déltà" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		hg_clone_$x gitrepo hgrepo-$x && | ||||
| 		git_clone_$x hgrepo-$x gitrepo2-$x && | ||||
|  | ||||
| 		HGENCODING=utf-8 hg_log hgrepo-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo2-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'file removal' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	echo beta > beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" | ||||
| 	mkdir foo && | ||||
| 	echo blah > foo/bar && | ||||
| 	git add foo && | ||||
| 	git commit -m "add foo" && | ||||
| 	git rm alpha && | ||||
| 	git commit -m "remove alpha" && | ||||
| 	git rm foo/bar && | ||||
| 	git commit -m "remove foo/bar" | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		( | ||||
| 		hg_clone_$x gitrepo hgrepo-$x && | ||||
| 		cd hgrepo-$x && | ||||
| 		hg_log . && | ||||
| 		hg manifest -r 3 && | ||||
| 		hg manifest | ||||
| 		) > "output-$x" && | ||||
|  | ||||
| 		git_clone_$x hgrepo-$x gitrepo2-$x && | ||||
| 		git_log gitrepo2-$x > "log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp output-hg output-git && | ||||
| 	test_cmp log-hg log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git tags' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	( | ||||
| 	git init -q gitrepo && | ||||
| 	cd gitrepo && | ||||
| 	git config receive.denyCurrentBranch ignore && | ||||
| 	echo alpha > alpha && | ||||
| 	git add alpha && | ||||
| 	git commit -m "add alpha" && | ||||
| 	git tag alpha && | ||||
|  | ||||
| 	echo beta > beta && | ||||
| 	git add beta && | ||||
| 	git commit -m "add beta" && | ||||
| 	git tag -a -m "added tag beta" beta | ||||
| 	) && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		hg_clone_$x gitrepo hgrepo-$x && | ||||
| 		hg_log hgrepo-$x > "log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp log-hg log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'hg author' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		( | ||||
| 		git init -q gitrepo-$x && | ||||
| 		cd gitrepo-$x && | ||||
|  | ||||
| 		echo alpha > alpha && | ||||
| 		git add alpha && | ||||
| 		git commit -m "add alpha" && | ||||
| 		git checkout -q -b not-master | ||||
| 		) && | ||||
|  | ||||
| 		( | ||||
| 		hg_clone_$x gitrepo-$x hgrepo-$x && | ||||
| 		cd hgrepo-$x && | ||||
|  | ||||
| 		hg co master && | ||||
| 		echo beta > beta && | ||||
| 		hg add beta && | ||||
| 		hg commit -u "test" -m "add beta" && | ||||
|  | ||||
| 		echo gamma >> beta && | ||||
| 		hg commit -u "test <test@example.com> (comment)" -m "modify beta" && | ||||
|  | ||||
| 		echo gamma > gamma && | ||||
| 		hg add gamma && | ||||
| 		hg commit -u "<test@example.com>" -m "add gamma" && | ||||
|  | ||||
| 		echo delta > delta && | ||||
| 		hg add delta && | ||||
| 		hg commit -u "name<test@example.com>" -m "add delta" && | ||||
|  | ||||
| 		echo epsilon > epsilon && | ||||
| 		hg add epsilon && | ||||
| 		hg commit -u "name <test@example.com" -m "add epsilon" && | ||||
|  | ||||
| 		echo zeta > zeta && | ||||
| 		hg add zeta && | ||||
| 		hg commit -u " test " -m "add zeta" && | ||||
|  | ||||
| 		echo eta > eta && | ||||
| 		hg add eta && | ||||
| 		hg commit -u "test < test@example.com >" -m "add eta" && | ||||
|  | ||||
| 		echo theta > theta && | ||||
| 		hg add theta && | ||||
| 		hg commit -u "test >test@example.com>" -m "add theta" && | ||||
|  | ||||
| 		echo iota > iota && | ||||
| 		hg add iota && | ||||
| 		hg commit -u "test <test <at> example <dot> com>" -m "add iota" | ||||
| 		) && | ||||
|  | ||||
| 		hg_push_$x hgrepo-$x gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
|  | ||||
| 		hg_log hgrepo2-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'hg branch' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		( | ||||
| 		git init -q gitrepo-$x && | ||||
| 		cd gitrepo-$x && | ||||
|  | ||||
| 		echo alpha > alpha && | ||||
| 		git add alpha && | ||||
| 		git commit -q -m "add alpha" && | ||||
| 		git checkout -q -b not-master | ||||
| 		) && | ||||
|  | ||||
| 		( | ||||
| 		hg_clone_$x gitrepo-$x hgrepo-$x && | ||||
|  | ||||
| 		cd hgrepo-$x && | ||||
| 		hg -q co master && | ||||
| 		hg mv alpha beta && | ||||
| 		hg -q commit -m "rename alpha to beta" && | ||||
| 		hg branch gamma | grep -v "permanent and global" && | ||||
| 		hg -q commit -m "started branch gamma" | ||||
| 		) && | ||||
|  | ||||
| 		hg_push_$x hgrepo-$x gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
|  | ||||
| 		hg_log hgrepo2-$x > "hg-log-$x" && | ||||
| 		git_log gitrepo-$x > "git-log-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp hg-log-hg hg-log-git && | ||||
| 	test_cmp git-log-hg git-log-git | ||||
| ' | ||||
|  | ||||
| test_expect_success 'hg tags' ' | ||||
| 	test_when_finished "rm -rf gitrepo* hgrepo*" && | ||||
|  | ||||
| 	for x in hg git | ||||
| 	do | ||||
| 		( | ||||
| 		git init -q gitrepo-$x && | ||||
| 		cd gitrepo-$x && | ||||
|  | ||||
| 		echo alpha > alpha && | ||||
| 		git add alpha && | ||||
| 		git commit -m "add alpha" && | ||||
| 		git checkout -q -b not-master | ||||
| 		) && | ||||
|  | ||||
| 		( | ||||
| 		hg_clone_$x gitrepo-$x hgrepo-$x && | ||||
|  | ||||
| 		cd hgrepo-$x && | ||||
| 		hg co master && | ||||
| 		hg tag alpha | ||||
| 		) && | ||||
|  | ||||
| 		hg_push_$x hgrepo-$x gitrepo-$x && | ||||
| 		hg_clone_$x gitrepo-$x hgrepo2-$x && | ||||
|  | ||||
| 		( | ||||
| 		git --git-dir=gitrepo-$x/.git tag -l && | ||||
| 		hg_log hgrepo2-$x && | ||||
| 		cat hgrepo2-$x/.hgtags | ||||
| 		) > "output-$x" | ||||
| 	done && | ||||
|  | ||||
| 	test_cmp output-hg output-git | ||||
| ' | ||||
|  | ||||
| test_done | ||||
| @@ -1,22 +1,16 @@ | ||||
| #!/usr/bin/env ruby | ||||
|  | ||||
| # | ||||
| # Copyright (c) 2019 Felipe Contreras | ||||
| # Copyright (c) 2019-2023 Felipe Contreras | ||||
| # | ||||
| # This script runs the tests for all versions of the components: | ||||
| #   hg, hggit and dulwich | ||||
| # This script runs the tests for all versions of hg. | ||||
| # | ||||
| # You can run it without arguments, in which case it reads the file | ||||
| # 'versions.txt' and executes all those checks. | ||||
| # You can run it without arguments, in which case it runs the tests for all | ||||
| # versions in `versions.txt`. | ||||
| # | ||||
| # Or you can pass the versions to check manually, like: | ||||
| # Or you can specify a single version manually: | ||||
| # | ||||
| #   ./check-versions hg:4.7 hggit:0.8.12 dulwich:0.19.7 | ||||
| # | ||||
| # Or you can pass just the hg version, the other versions are fetched from | ||||
| # 'versions.txt': | ||||
| # | ||||
| #   ./check-versions hg:5.0 | ||||
| #   ./check-versions 6.3 | ||||
| # | ||||
|  | ||||
| require 'fileutils' | ||||
| @@ -62,46 +56,26 @@ def check_version(a, b) | ||||
|   (a <=> b) >= 0 | ||||
| end | ||||
|  | ||||
| # Component {{{1 | ||||
| # Hg {{{1 | ||||
|  | ||||
| class Component | ||||
| class Hg | ||||
|  | ||||
|   attr_reader :id | ||||
|  | ||||
|   def initialize(id, url, kind: nil, **args) | ||||
|     @id = id | ||||
|     @url = url | ||||
|     @kind = kind || (url.start_with?('git') ? :git : :hg) | ||||
|     @tool = @kind.to_s | ||||
|     @checkout_fix = args[:checkout_fix] | ||||
|     @version_format = args[:version_format] | ||||
|   def initialize | ||||
|     @url = 'https://www.mercurial-scm.org/repo/hg' | ||||
|   end | ||||
|  | ||||
|   def dir | ||||
|     "#{$workdir}/#{@id}" | ||||
|   end | ||||
|  | ||||
|   def get_version(version) | ||||
|     return @kind == :hg ? 'tip' : '@' if version == '@' | ||||
|     @version_format ? @version_format % version : version | ||||
|     "#{$workdir}/hg" | ||||
|   end | ||||
|  | ||||
|   def clone | ||||
|     run_cmd [@tool, 'clone', '-q', @url, dir] | ||||
|     run_cmd %w[hg clone -q] + [@url, dir] | ||||
|   end | ||||
|  | ||||
|   def checkout(version) | ||||
|     Dir.chdir(dir) do | ||||
|       case @kind | ||||
|       when :hg | ||||
|         cmd = %w[update --clean] | ||||
|       when :git | ||||
|         cmd = %w[reset --hard] | ||||
|       else | ||||
|         cmd = %w[checkout] | ||||
|       end | ||||
|       run_cmd [@tool] + cmd + ['-q', get_version(version)] | ||||
|       @checkout_fix.call(version) if @checkout_fix | ||||
|       run_cmd %w[hg update --clean -q] << version | ||||
|       checkout_fix(version) | ||||
|     end | ||||
|   end | ||||
|  | ||||
| @@ -112,6 +86,18 @@ class Component | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def checkout_fix(version) | ||||
|     FileUtils.cp('hg', "#{$builddir}/bin/") | ||||
|  | ||||
|     return if check_version(version, '4.3') | ||||
|  | ||||
|     if run_cmd %W[hg import -q --no-commit #{__dir__}/hg_setup_hack_2.4.patch], fatal: false | ||||
|       File.write('.hg_force_version', "%s\n" % version) | ||||
|     else | ||||
|       File.write('mercurial/__version__.py', "version = \"%s\"\n" % version) | ||||
|     end | ||||
|   end | ||||
|  | ||||
| end | ||||
|  | ||||
| # Functions {{{1 | ||||
| @@ -121,16 +107,14 @@ def setup | ||||
|   FileUtils.mkdir_p(dirs.map { |e| "#{$builddir}/#{e}" }) | ||||
|   FileUtils.mkdir_p($workdir) | ||||
|  | ||||
|   $components.each do |id, component| | ||||
|     next if File.exists?(component.dir) | ||||
|   return if File.exist?($hg.dir) | ||||
|  | ||||
|     if $verbosity < HIGH | ||||
|       puts "Cloning #{component.id}" | ||||
|     else | ||||
|       title "Cloning #{component.id}" | ||||
|     end | ||||
|     component.clone | ||||
|   if $verbosity < HIGH | ||||
|     puts "Cloning hg" | ||||
|   else | ||||
|     title "Cloning hg" | ||||
|   end | ||||
|   $hg.clone | ||||
| end | ||||
|  | ||||
| def test_env(paths: nil) | ||||
| @@ -163,31 +147,14 @@ def run_tests(tests) | ||||
|   end | ||||
| end | ||||
|  | ||||
| def versions_to_s(versions) | ||||
|   versions.map { |k,v| "#{k}:#{v}" }.join(' ') | ||||
| end | ||||
| def check(version) | ||||
|   section version | ||||
|  | ||||
| def versions_from_args(args) | ||||
|   args.map { |e| k, v = e.split(':'); [k.to_sym, v] }.to_h | ||||
| end | ||||
|   title "Checking out hg #{version}" | ||||
|   $hg.checkout(version) | ||||
|  | ||||
| def versions_from_s(str) | ||||
|   versions_from_args(str.split(' ')) | ||||
| end | ||||
|  | ||||
| def check(versions) | ||||
|   section versions_to_s(versions) | ||||
|  | ||||
|   versions.each do |id, version| | ||||
|     component = $components[id] | ||||
|     next unless component | ||||
|  | ||||
|     title "Checking out #{component.id} #{version}" | ||||
|     component.checkout(version) | ||||
|  | ||||
|     title "Building #{component.id}" | ||||
|     component.build | ||||
|   end | ||||
|   title "Building hg" | ||||
|   $hg.build | ||||
|  | ||||
|   paths = { | ||||
|     PATH: "#{$builddir}/bin", | ||||
| @@ -200,103 +167,31 @@ def check(versions) | ||||
|   end | ||||
| end | ||||
|  | ||||
| # Add components {{{1 | ||||
|  | ||||
| $components = {} | ||||
|  | ||||
| def add_component(id, url, **args) | ||||
|   $components[id] = Component.new(id, url, **args) | ||||
| end | ||||
|  | ||||
| hg_checkout_fix = lambda do |version| | ||||
|   FileUtils.cp('hg', "#{$builddir}/bin/") | ||||
|  | ||||
|   return if check_version(version, '4.3') | ||||
|  | ||||
|   if run_cmd %W[hg import -q --no-commit #{__dir__}/hg_setup_hack_2.4.patch], fatal: false | ||||
|     File.write('.hg_force_version', "%s\n" % version) | ||||
|   else | ||||
|     File.write('mercurial/__version__.py', "version = \"%s\"\n" % version) | ||||
|   end | ||||
| end | ||||
|  | ||||
| add_component(:hg, 'https://www.mercurial-scm.org/repo/hg', checkout_fix: hg_checkout_fix) | ||||
|  | ||||
| hggit_checkout_fix = lambda do |version| | ||||
|   return unless check_version(version, '0.8.0') | ||||
|  | ||||
|   run_cmd %W[hg import -q --no-commit #{__dir__}/hggit_rename_fix_0.8.0.patch], fatal: false | ||||
| end | ||||
|  | ||||
| add_component(:hggit, 'https://bitbucket.org/durin42/hg-git', checkout_fix: hggit_checkout_fix) | ||||
|  | ||||
| add_component(:dulwich, 'https://github.com/dulwich/dulwich.git', version_format: 'dulwich-%s', kind: :git) | ||||
|  | ||||
| def load_checks(file) | ||||
|   file.each do |e| | ||||
|     e.chomp! | ||||
|     next if e.empty? or e.start_with?('#') | ||||
|     content, comment = e.split(' # ') | ||||
|     versions = versions_from_s(content) | ||||
|     $checks << versions | ||||
|   end | ||||
| end | ||||
|  | ||||
| def store_results(file) | ||||
|   $results.each do |versions, result| | ||||
|     content = versions_to_s(versions) | ||||
|     comment = result ? 'OK' : 'FAIL' | ||||
|     file.puts '%s # %s' % [content, comment] | ||||
|   end | ||||
| end | ||||
| $hg = Hg.new() | ||||
|  | ||||
| # Main {{{1 | ||||
|  | ||||
| setup | ||||
|  | ||||
| $checks = [] | ||||
| $results = [] | ||||
|  | ||||
| $versions = versions_from_args(ARGV) | ||||
| $version = ARGV.first | ||||
| $checks = File.readlines(__dir__ + '/versions.txt', chomp: true) | ||||
| $results = File.open(__dir__ + '/results.txt', 'w') | ||||
|  | ||||
| File.open("#{__dir__}/versions.txt") do |f| | ||||
|   load_checks(f) | ||||
| end | ||||
|  | ||||
| if $versions.size == 1 and $versions.key?(:hg) | ||||
|   # mode 1 | ||||
|   $verbosity = LOW | ||||
|  | ||||
|   if ['@', nil].include?($versions[:hg]) | ||||
|     versions = $checks.last | ||||
|     versions[:hg] = $versions[:hg] if $versions[:hg] | ||||
|   else | ||||
|     versions = $checks.find { |e| e[:hg] == $versions[:hg] } | ||||
|     exit 1 unless versions | ||||
|   end | ||||
|  | ||||
|   exit check(versions) ? 0 : 1 | ||||
| elsif not $versions.empty? | ||||
|   # mode 2 | ||||
| if $version | ||||
|   $verbosity = HIGH | ||||
|  | ||||
|   exit check(versions) ? 0 : 1 | ||||
|   exit check($version) ? 0 : 1 | ||||
| else | ||||
|   # mode 3 | ||||
|   $verbosity = QUIET | ||||
|  | ||||
|   at_exit do | ||||
|     File.open("#{__dir__}/results.txt", 'w') do |f| | ||||
|       store_results(f) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   failures = 0 | ||||
|  | ||||
|   $checks.each do |versions| | ||||
|     result = check(versions) | ||||
|   $checks.each do |version| | ||||
|     result = check(version) | ||||
|     failures += 1 unless result | ||||
|     $results << [versions, result] | ||||
|     $results.puts '%s # %s' % [version, result ? 'OK' : 'FAIL'] | ||||
|   end | ||||
|  | ||||
|   exit 1 unless failures == 0 | ||||
|   | ||||
| @@ -1,22 +0,0 @@ | ||||
| diff --git a/hggit/git_handler.py b/hggit/git_handler.py | ||||
| --- a/hggit/git_handler.py | ||||
| +++ b/hggit/git_handler.py | ||||
| @@ -693,6 +693,8 @@ | ||||
|      def import_git_commit(self, commit): | ||||
|          self.ui.debug(_("importing: %s\n") % commit.id) | ||||
|   | ||||
| +        extra_in_message = self.ui.configbool('git', 'debugextrainmessage', False) | ||||
| + | ||||
|          detect_renames = False | ||||
|          (strip_message, hg_renames, | ||||
|           hg_branch, extra) = git2hg.extract_hg_metadata( | ||||
| @@ -703,7 +705,8 @@ | ||||
|              # renames detected from Git. This is because we export an extra | ||||
|              # 'HG:rename-source' Git parameter when this isn't set, which will | ||||
|              # break bidirectionality. | ||||
| -            extra['hg-git-rename-source'] = 'git' | ||||
| +            if not extra_in_message: | ||||
| +                extra['hg-git-rename-source'] = 'git' | ||||
|          else: | ||||
|              renames = hg_renames | ||||
|   | ||||
| @@ -1,33 +1,47 @@ | ||||
| # vi: ft=ruby | ||||
|  | ||||
| hg:2.4 hggit:0.4.0 dulwich:0.9.0 # 2013_02 | ||||
| hg:2.5 hggit:0.4.0 dulwich:0.9.0 # 2013_02 | ||||
| hg:2.6 hggit:0.4.0 dulwich:0.9.0 # 2013_02 | ||||
| hg:2.7 hggit:0.4.0 dulwich:0.9.0 # 2013_02 | ||||
| hg:2.8 hggit:0.4.0 dulwich:0.9.0 # 2013_02 | ||||
| hg:2.9 hggit:0.4.0 dulwich:0.9.0 # 2013_02 | ||||
|  | ||||
| hg:3.0 hggit:0.7.0 dulwich:0.10.0 # 2014_11 | ||||
| hg:3.1 hggit:0.7.0 dulwich:0.10.0 # 2014_11 | ||||
| hg:3.2 hggit:0.7.0 dulwich:0.10.0 # 2014_11 | ||||
|  | ||||
| hg:3.3 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
| hg:3.4 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
| hg:3.5 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
| hg:3.6 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
| hg:3.7 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
| hg:3.8 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
| hg:3.9 hggit:0.8.4 dulwich:0.13.0 # 2016_01 | ||||
|  | ||||
| hg:4.0 hggit:0.8.10 dulwich:0.18.0 # 2017_11 | ||||
| hg:4.1 hggit:0.8.10 dulwich:0.18.0 # 2017_11 | ||||
| hg:4.2 hggit:0.8.10 dulwich:0.18.0 # 2017_11 | ||||
| hg:4.3 hggit:0.8.10 dulwich:0.18.0 # 2017_11 | ||||
| hg:4.4 hggit:0.8.10 dulwich:0.18.0 # 2017_11 | ||||
|  | ||||
| hg:4.5 hggit:0.8.11 dulwich:0.18.0 # 2018_02 | ||||
| hg:4.6 hggit:0.8.12 dulwich:0.19.7 # 2018_10 | ||||
| hg:4.7 hggit:0.8.12 dulwich:0.19.7 # 2018_10 | ||||
| hg:4.8 hggit:@ dulwich:0.19.11 | ||||
| hg:4.9 hggit:@ dulwich:0.19.11 | ||||
| hg:5.0 hggit:@ dulwich:0.19.11 | ||||
| 2.4 | ||||
| 2.5 | ||||
| 2.6 | ||||
| 2.7 | ||||
| 2.8 | ||||
| 2.9 | ||||
| 3.0 | ||||
| 3.1 | ||||
| 3.2 | ||||
| 3.3 | ||||
| 3.4 | ||||
| 3.5 | ||||
| 3.6 | ||||
| 3.7 | ||||
| 3.8 | ||||
| 3.9 | ||||
| 4.0 | ||||
| 4.1 | ||||
| 4.2 | ||||
| 4.3 | ||||
| 4.4 | ||||
| 4.5 | ||||
| 4.6 | ||||
| 4.7 | ||||
| 4.8 | ||||
| 4.9 | ||||
| 5.0 | ||||
| 5.1 | ||||
| 5.2 | ||||
| 5.3 | ||||
| 5.4 | ||||
| 5.5 | ||||
| 5.6 | ||||
| 5.7 | ||||
| 5.8 | ||||
| 5.9 | ||||
| 6.0 | ||||
| 6.1 | ||||
| 6.2 | ||||
| 6.3 | ||||
| 6.4 | ||||
| 6.5 | ||||
| 6.6 | ||||
| 6.7 | ||||
| 6.8 | ||||
| 6.9 | ||||
| 7.0 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user