400 Commits
v0.1 ... master

Author SHA1 Message Date
Mark Nauwelaerts
88b2756e43 t: post-merge adjust of test-lib.sh 2025-08-30 20:31:47 +02:00
Mark Nauwelaerts
d000a0b5e6 t: post-merge align of main-push test 2025-08-23 18:12:41 +02:00
Mark Nauwelaerts
4e119d9ea6 t: post-merge align of helper test 2025-08-23 18:12:41 +02:00
Mark Nauwelaerts
e31f83cbc5 Merge branch 'felipec' 2025-08-23 15:39:32 +02:00
Mark Nauwelaerts
5e1aa3a8e0 Merge commit 'bad0a3e5e5dd8352b3ea67d6efa8584ebde5311e' into felipec 2025-08-23 15:30:30 +02:00
Mark Nauwelaerts
ce7ddae09a Merge commit 'f4cdd20cb106c9e0ba57bc63b4231f9da6e72513' into felipec 2025-08-23 15:27:12 +02:00
Felipe Contreras
bad0a3e5e5 check-versions: test hg 7.0 2025-08-02 03:54:13 -06:00
Felipe Contreras
705f9ecaec github: enable windows test 2025-08-02 03:49:15 -06:00
Felipe Contreras
7c3eccdb93 t: cleanup win check 2025-08-02 03:44:52 -06:00
Felipe Contreras
44d09e7d37 t: check for MinGW32 2025-08-02 03:44:52 -06:00
Felipe Contreras
f87d0bc1a1 github: update python version 2025-08-02 03:44:28 -06:00
Felipe Contreras
54804bc402 github: update actions 2025-08-02 03:44:28 -06:00
Felipe Contreras
99c02f49df github: cleanup 2025-08-02 03:44:28 -06:00
Felipe Contreras
39960e1ae8 github: use prove 2025-08-02 03:44:28 -06:00
Felipe Contreras
5353a87001 t: allow execution from other dirs 2025-08-02 03:44:28 -06:00
Felipe Contreras
9a80e68234 t: update to sharness 1.2.1 2025-08-02 03:44:28 -06:00
Felipe Contreras
f4cdd20cb1 t: rename directory 2025-08-01 19:05:51 -06:00
Mark Nauwelaerts
16b33919e4 Release v1.0.5 2025-06-29 21:34:12 +02:00
Mark Nauwelaerts
9813797360 Transform invalid reserved pathname components
Fixes mnauw/git-remote-hg#58
2025-05-04 12:45:41 +02:00
Mark Nauwelaerts
e1a9c3e91b Update loading source file as module 2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
a8f6d92613 helper: add mapfile subcommand
Fixes mnauw/git-remote-hg#55
2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
4b8a307400 helper: use proper variable in error message 2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
6d75435eab helper: align update of reference to shared hg repo
... to use a relative path where possible
2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
d47a4abdae Always ensure reference to shared hg repo is up to date 2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
afdb8943ea ci: disable trigger on push 2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
dc1be060d1 README: drop mention of supported version
... as the intention is always to support the latest anyway
2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
13781788eb README: add a note about broken hg-git compatibility mode 2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
5061e6a322 README: minor note on notes 2025-05-04 12:19:35 +02:00
Mark Nauwelaerts
587099b968 Disable a hg-git mimic attempt
This essentially mostly reverts b029ac0500,
as we have no way to properly decide on those extra pieces.

hg-git uses commit extra metadata, which is not supported by fast-import
or fast-export, and until/unless that changes there is no way to match
hg-git.  Trying to do so in contorted ways only adds confusion.
2025-05-04 12:17:27 +02:00
Mark Nauwelaerts
b5f104364f test: ensure original behaviour in hg-git test 2025-05-03 12:18:25 +02:00
Mark Nauwelaerts
a48d4fd7fb test: post-merge align of main-push test 2025-05-03 12:18:25 +02:00
Mark Nauwelaerts
301552278a test: post-merge align of helper test 2025-05-02 16:13:19 +02:00
Mark Nauwelaerts
fddbbfe990 Merge branch 'felipec'
Integrate changes from felipec where appropriate and still relevant.
2025-05-01 20:18:03 +02:00
Mark Nauwelaerts
c329c9690a Merge commit '408333afca931970d19c57bb697cdf83f6abcbef' into felipec
These changes can be merged with limited conflict resolution.
2025-05-01 20:00:37 +02:00
Mark Nauwelaerts
6c36268028 Merge commit '474cacd81d0f34717aebc6df473406285d5868ad' into felipec
These changes can be merged with limited conflict resolution.
2025-05-01 19:48:36 +02:00
Mark Nauwelaerts
893dd9434f Merge commit '7713b7ecefea9f0df2970079086fe318e3d26311' into felipec
These changes have been discarded.

While it may involve ancient API, there is limited gain wrt complexity,
so might as well leave in place.
2025-05-01 19:38:27 +02:00
Mark Nauwelaerts
4ddbfeb9c8 Merge commit '463f397ba49b9f5f416c1cf85c1104c3939be224' into felipec
Discard change, which now follows a similar approach to what was
introduced long ago in c3f02d39ad.
Caution is also required in subsequent imports as considered in
a59e1246a2.
2025-05-01 16:20:56 +02:00
Mark Nauwelaerts
93271a4e1b Merge commit 'e774ad2d96ae27e23c8ede88384bb1c085d631e8' into felipec
Accept trivial change.
2025-05-01 16:20:16 +02:00
Mark Nauwelaerts
36706dffe6 Merge commit '086ca235076d7450d3e46e8f80f483b895856777' into felipec
Discard superfluous cleanup.
2025-05-01 16:07:24 +02:00
Mark Nauwelaerts
da532bf6f4 Merge commit '7c373be665ebcf794a297b3c98afd9d94365d9f9' into felipec
These changes can be merged and accepted with limited conflict resolution.
2025-05-01 16:05:05 +02:00
Mark Nauwelaerts
aa1d0bc152 Merge commit '7908c70efbd0420e21c2b0b7841b61e3b933be51' into felipec
These changes can be merged with limited conflict resolution.
2025-05-01 16:02:47 +02:00
Mark Nauwelaerts
bdbe62256a Merge commit '8025945a62d16ef078299ad5903081f250d762ed' into felipec
These changes can be merged with some adjustments.
That is, only conditionally prefer some newer API, but otherwise
prefer current code paths, which have been tried and tested for a
long time through various version (both python and hg).
2025-04-30 20:55:24 +02:00
Mark Nauwelaerts
8acf139e44 Merge commit 'b8b9a2f571c322bb3fe8a19c102a0f75fe9f3a9a' into felipec
These changes can be merged with limited to no conflict resolution.
2025-04-30 20:31:41 +02:00
Mark Nauwelaerts
1df692295c Merge commit 'f032d3617bb47585f20006abee83d7309498c17d' into felipec
This change is part of port to python v3 and can as such be discarded.
2025-04-30 20:18:32 +02:00
Mark Nauwelaerts
027e1a16f0 Merge commit '60a1d7ae7a60988f122d8d9ba9ad3c693c5141ae' into felipec
These changes can be merged with limited conflict resolution.
2025-04-30 19:16:33 +02:00
Mark Nauwelaerts
723e6c76fc Merge commit '9b54c626bcf25d390861b430145e96af3ec8459c' into felipec
The removal of support for older version can reduce clutter and ease
maintenance, but in this case such gains are marginal, and there would
then only be loss (of older functionality).

As such, this change is discarded, and older version support is kept.
2025-04-30 18:34:29 +02:00
Mark Nauwelaerts
2529c986c2 Merge commit 'd51f508916d543f987868dd6f7072c72e8f692b2' into felipec
These changes can be merged with limited to no conflict resolution.
2025-04-30 18:30:58 +02:00
Mark Nauwelaerts
ab398ade1d Merge commit '7196dac02d94105586305462be5c15a812c6f7de' into felipec
These changes can be mostly accepted and merged with limited resolution,
especially since hg-git testing is mostly disabled and discarded in
future commits.
2025-04-29 21:56:56 +02:00
Mark Nauwelaerts
e1d25cf97c Merge commit 'b4c3277f72f995cc0babcdc5bc6f6d0e2254acc3' into felipec
These changes can be merged with limited conflict resolution.
2025-04-29 21:18:04 +02:00
Mark Nauwelaerts
0fe1e359ec Merge commit '7394fc890e76ec3919fa30048338a9cbb59ce899' into felipec
This commit can be discarded as it is not relevant; revwalk() is used
in stead of gitrange().  The latter is based on recorded tips, which
are also no longer in use, as that approach is not quite robust.
It is also inefficient when fetching large number of new bookmarks
(for which there can be no pre-tracked tip).
2025-04-29 20:53:25 +02:00
Mark Nauwelaerts
498c615051 Merge commit '22229dd738ae3d0752b293cca1cf948c1d154cfa' into felipec
These changes can be merged with limited to no conflict resolution.
2025-04-29 20:48:13 +02:00
Mark Nauwelaerts
6b6aa9deaa Merge tag 'v0.6' into felipec
These changes involve a port to python3.  These can mostly be discarded,
as such port has already been done in an alternative way, which supports
both v2 and v3.
2025-04-28 18:53:34 +02:00
Mark Nauwelaerts
2685f56c7c Merge tag 'v0.5' into felipec
These changes can be merged with limited to no conflict resolution.
2025-04-28 18:37:33 +02:00
Mark Nauwelaerts
3314ce3dda Makefile: use lighter asciidoctor iso asciidoc 2025-04-28 17:24:22 +02:00
Felipe Contreras
408333afca github: use newer hg versions 2025-03-08 08:48:47 -06:00
Felipe Contreras
c861db6add check-versions: add newer versions 2025-03-08 08:32:03 -06:00
Felipe Contreras
d2a3a646af test: unset user some config 2025-03-08 08:30:24 -06:00
Felipe Contreras
f00911668a Avoid decoding some binary stuff 2025-03-08 02:01:54 -06:00
Felipe Contreras
474cacd81d check-versions: fix for newer ruby versions 2025-03-07 23:53:09 -06:00
Mark Nauwelaerts
e4d87d5e2c Use raw literals for some regexps
Fixes mnauw/git-remote-hg#57
2025-02-08 21:19:29 +01:00
Felipe Contreras
615cc7fe04 github: disable windows tests
It's not working. Probably related to actions/runner-images#7253.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2024-03-07 01:07:07 -06:00
Dan Rose
79e75991ab Use raw strings for regexes
Fixes #94.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2024-03-07 00:28:50 -06:00
Mark Nauwelaerts
b029ac0500 Improve hg-git compatibility mode
... by adjusting to some hg-git changes

See mnauw/git-remote-hg#55
2023-05-07 13:21:45 +02:00
Felipe Contreras
7713b7ecef Remove push_unsafe()
It's not needed anymore.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-05 12:29:28 -06:00
Felipe Contreras
b274b8057e Don't force public pushes
This is something that needs to explicitly happen.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-05 12:29:28 -06:00
Felipe Contreras
451e31022a Restrict common discovery
This was added in hg 4.5.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-05 12:29:28 -06:00
Felipe Contreras
9c61c09ebf Remove support for lock-based unbundling
This was deprecated in 0.9.1 and support for those servers dropped in
4.4.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-05 12:29:23 -06:00
Felipe Contreras
463f397ba4 Remove last-note
We can take advantage of `ref^0` and let `git fast-import` figure out
the most recent commit.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-04 15:07:19 -06:00
Felipe Contreras
e774ad2d96 Fix initial marks version
[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-04 09:40:10 -06:00
Felipe Contreras
086ca23507 Trivial cleanups
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-04 07:45:58 -06:00
Felipe Contreras
7c373be665 test: test against hg 6.4
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-05-04 07:20:51 -06:00
Felipe Contreras
3bfec5fc6f github: give a name to the action
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-22 18:17:20 -06:00
Felipe Contreras
7908c70efb Trivial simplifications
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 02:09:17 -06:00
Felipe Contreras
7cff2c6adb Simplify export_file args
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 02:07:45 -06:00
Felipe Contreras
9c5b8835f4 Get rid of export_files
It's not necessary.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 02:02:11 -06:00
Felipe Contreras
537e5a4735 Reorganize export_files
No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 01:58:42 -06:00
Felipe Contreras
8025945a62 Simpler get_filechanges algorithm
The status method achieves the same thing as the current code.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 01:54:10 -06:00
Felipe Contreras
33dccdfab0 Simplify get_filechanges
No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 01:47:48 -06:00
Felipe Contreras
4ad9c8d70c Reorganize get_filechanges
So it's more extensible.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 01:44:31 -06:00
Felipe Contreras
740c681c1d Trivial style change
More idiomatic.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 01:39:33 -06:00
Felipe Contreras
995179444c Trivial simplification
When there's no parents the files are the same as the manifest.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-20 01:37:49 -06:00
Felipe Contreras
e6c479c136 Cleanup timezone stuff
No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-14 04:10:54 -06:00
Felipe Contreras
b8b9a2f571 Use relative option to hg.share
When available.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 22:48:07 -06:00
Felipe Contreras
4c50223dba remote-hg: remove shared repo upgrade
We are not in 2013 anymore.

This reverts commit 8f9a87c (remote-hg: add shared repo upgrade,
2013-08-09).

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 22:47:53 -06:00
Felipe Contreras
35d32d5a75 Remove ancient marks upgrade path
It's safe to safe everyone already moved on since 2013.

This reverts d379f37 (remote-hg: upgrade version 1 marks, 2013-05-24).

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 21:49:05 -06:00
Felipe Contreras
7f6a843f0d github: add windows job
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 18:46:30 -06:00
Felipe Contreras
63cf2780ba test: fixes for Windows
It's not clear if these tests can't work, or don't work at the moment,
but at least some seem to be the fault of hg, not us.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 18:45:17 -06:00
Felipe Contreras
f032d3617b Improve output writing
Let's avoid all python weirdness and just write directly.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 11:52:05 -06:00
Mark Nauwelaerts
60a1d7ae7a Fix for paths in Windows
Rewritten-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 11:52:05 -06:00
Felipe Contreras
10aec96d88 Simplify absolute path fix
This actually works on Windows.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-07 11:33:30 -06:00
Felipe Contreras
9b54c626bc Remove support for hg < 4.0
2016 is ancient anyway.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
d51f508916 check-versions: trivial results cleanup 2023-03-06 15:40:44 -06:00
Felipe Contreras
9916fead46 github: trivial update
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
09c4726083 check-versions: simplify for a single component
No need for all the extra complexity just for hg.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
bb663c032f github: use standard hg packages
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
b590aec106 check-versions: remove code for other tools
Only support hg.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
4496af4a5c check-versions: remove hg hack
It was only needed for hg-git tests.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
890080673b check-versions: remove hg-git stuff
It's not worth it to keep trying to run this.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
5e6ef0a1d5 test: properly check for mercurial
We want to fail if it's not present, not skip the tests.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
a1e2c4acc9 test: remove pointless prereq checks
The prereq check was necessary in upstream git, not here where it's a
noop.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:40:44 -06:00
Felipe Contreras
7196dac02d Merge branch 'hg-git-revamp'
* hg-git-revamp:
  test: enable hg-git tests
  test: hg-git: trivial cleanup
  test: hg-git: general cleanup
  test: hg-git: fetch output from expected dir
  test: add expected output
  test: hg-git: add test_cmp_expected helper
  test: hg-git: add helper functions
  test: switch to bash
  test: hg-git: add main helper
  test: hg-git: simplify hg log filter
  test: relax hg-git checks
  test: hg-git: cleanup
2023-03-06 15:39:23 -06:00
Felipe Contreras
a8bb2a28a3 test: enable hg-git tests
They have been working for a long time but the standard packages needed
to be patched with check-versions to run them successfully.

Now that the expected output is stored we don't need to patch anything
and they can just be run.

This reverts commit b022367aef.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:18:53 -06:00
Felipe Contreras
ffcb41cc52 test: hg-git: trivial cleanup
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:18:53 -06:00
Felipe Contreras
9949745533 test: hg-git: general cleanup
Now that we don't have to run hg-git the code is much simpler.

No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:18:52 -06:00
Felipe Contreras
83620648ab test: hg-git: fetch output from expected dir
So we don't actually have to run hg-git every time (it's broken most of
the time anyway).

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:09:02 -06:00
Felipe Contreras
30a2d61bdf test: add expected output
Generated with: hg:6.3 hggit:1.0.1 dulwich:0.20.50

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:09:02 -06:00
Felipe Contreras
2fdb786fc4 test: hg-git: add test_cmp_expected helper
No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:09:02 -06:00
Felipe Contreras
79797918ff test: hg-git: add helper functions
It's tedious to do almost exactly the same thing over and over.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:09:02 -06:00
Felipe Contreras
d45d5cde50 test: switch to bash
We are using some bash-specific tricks.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 15:09:02 -06:00
Felipe Contreras
7078666c77 test: hg-git: add main helper
Simplifies current code and will be useful later.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 09:55:03 -06:00
Felipe Contreras
08e453f8db test: hg-git: simplify hg log filter
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 09:55:03 -06:00
Felipe Contreras
ec7119d0ef test: relax hg-git checks
We don't care about the revision number of the commits, only the
topology.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 09:55:03 -06:00
Felipe Contreras
6ae5e3961e test: hg-git: cleanup
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 09:55:03 -06:00
Felipe Contreras
b4c3277f72 github: trigger actions on all branches
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-06 09:42:51 -06:00
Felipe Contreras
de9bf35388 test: include sharness properly
So that it can be overridden.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-05 22:40:09 -06:00
Felipe Contreras
857d68708b test: trivial cleanups
TEST_DIRECTORY doesn't even exist in sharness.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-05 22:32:27 -06:00
Felipe Contreras
7394fc890e Simplify gitrange
The internal function for `a %% b` is marginally faster, and much
simpler.

Nowadays most versions of hg should have it.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-02 16:54:33 -06:00
Felipe Contreras
22229dd738 Only report success after successful push
Otherwise git core will update the namespaced refs, and show success to
the user, even in the case of a crash.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-01 11:38:29 -06:00
Felipe Contreras
5cd03ad0fd github: update python version
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-01 11:08:56 -06:00
Felipe Contreras
bf7ad934d7 check-versions: update
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2023-03-01 11:08:27 -06:00
Mark Nauwelaerts
426ed618b2 Release v1.0.4 2022-12-07 19:10:40 +01:00
Mark Nauwelaerts
5f34d049b9 test: adjust configuration to recent git
... to allow file protocol

Fixes mnauw/git-remote-hg#53
2022-12-06 22:57:29 +01:00
Mark Nauwelaerts
ea7e9bf31a helper: align getenv compatibility helper 2022-10-22 18:46:52 +02:00
Mark Nauwelaerts
a3a36883c5 Ensure fallback getenvb returns bytes 2022-10-22 18:46:47 +02:00
Jeremiah Blanchard
0fdd28319a Fixes bug where compat.getenv fails on Windows due to bytes type (when string expected) (tested on Python 3.10) 2022-10-22 18:28:04 +02:00
Felipe Contreras
a5bc03d4d6 doc: use asdiidoctor
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-19 18:41:53 -05:00
Felipe Contreras
104e8895d6 doc: update and cleanup
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-19 18:37:24 -05:00
Felipe Contreras
30f31c13ce Skip close check for non-local branches
Apparently nowadays some remotes contain a bunch of topic branches which
are not pulled by default.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-10 23:53:45 -05:00
Felipe Contreras
485806e1e3 Dump data contents as-is
We don't care if it's valid utf-8 or not, just dump it.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-10 21:13:02 -05:00
Felipe Contreras
6e13c1c818 github: run tests with python3
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-08 00:33:10 -05:00
Felipe Contreras
ce38d52ce5 check-versions: add latest version
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-08 00:01:41 -05:00
Felipe Contreras
6b8ee2f1b6 check-versions: update version list
All these work with python3, and finally we are up-to-date.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-08 00:01:41 -05:00
Felipe Contreras
b3b9b5de39 Enable python3 support
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-08 00:01:41 -05:00
Felipe Contreras
34ba087896 Use unicode_escape
Seems to work in both python2 and python3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
4aec2fe3cc Properly print binary data
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
e892cb6ce3 Decode commit data
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
59ad50c6d0 Encode more stuff
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
b8c8b1fd00 Encode hg literals
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
0cf8b2c20a Encode more hg stuff
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
8c3cde6be7 Encode hg urls
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
ccee8909ff Encode hg rev and hex stuff
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
dd6b72df21 Encode and decode {hg,git}ref
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
01d619ad3c Encode hg tag stuff
In preparation for python3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
9d45e70fce Encode hg branch stuff
In preparation for python3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
055cec1aa7 Encode hg bookmark stuff
In preparation for python3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
7d50fa42c1 Decode and encode parsed strings
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:21 -05:00
Felipe Contreras
f6676e6d86 Avoid python2 iteritems()
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:58:19 -05:00
Felipe Contreras
cac075744d Use python3 print syntax
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:30:38 -05:00
Felipe Contreras
19633eaf36 Improve urllib imports
So it's more extensible for when we move to python3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:30:38 -05:00
Felipe Contreras
900a55e974 Use more standard python3 idioms
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:30:38 -05:00
Felipe Contreras
d1f60c445e readme: general updates
[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 23:18:16 -05:00
Felipe Contreras
bd3f404d34 readme: python3 support is ready
[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-07 22:33:46 -05:00
Felipe Contreras
dcf96f31db readme: more description about mnauw's fork
[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 23:27:09 -05:00
Felipe Contreras
795b88e16c readme: minor improvements
[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 23:22:48 -05:00
Felipe Contreras
20366b4b20 Trivial cleanup
rev_marks and tips are already strings.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 20:31:16 -05:00
Felipe Contreras
1f5134062e Add debug helper
It's kind of tedious to always add something like this.

[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 17:33:37 -05:00
Felipe Contreras
2313dc2ca0 readme: update
[no ci]

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 02:58:51 -05:00
Felipe Contreras
0e52a6c883 check-versions: add last python2 combination
Mercurial 5.8 does keep working with python 2.7, but hggit 0.10.1
doesn't, and neither does dulwich 0.20.0.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 02:22:33 -05:00
Felipe Contreras
e24a713dc9 check-versions: add hack for hg 5.7
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-08-05 01:29:05 -05:00
Felipe Contreras
122b7f5da2 Remove annoying warning
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 05:16:36 -05:00
Felipe Contreras
98c1c9263e github: update hg versions
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 04:23:14 -05:00
Felipe Contreras
85293dcf69 check-versions: add 2020 versions
Also, update the hggit patch for 0.9.0.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 04:23:14 -05:00
Felipe Contreras
970883c46c check-versions: add more versions
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 01:25:14 -05:00
Felipe Contreras
ad77f125b7 travis: remove crap
No longer open.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 01:25:14 -05:00
Felipe Contreras
5dcd6df3c8 github: cache check-versions stuff
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:59:58 -05:00
Felipe Contreras
ed80437db4 github: use a matrix of hg versions
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:48:57 -05:00
Felipe Contreras
0a1e8ecbc7 github: add simple workflow
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:38:40 -05:00
Felipe Contreras
6d6504d1fd test: fix for latest versions of git
Since git 2.34 the big push with force test is broken thanks to:

726a228dfb (fast-export: fix surprising behavior with --first-parent, 2021-12-16)

Since this only affects pushing multiple heads to the same branch, it
probably is not that important.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:38:40 -05:00
Felipe Contreras
237ff083af check-versions: update versions
These combinations seem to work.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:19:44 -05:00
Felipe Contreras
0c8f8571c7 check-versions: update hggit url
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:19:44 -05:00
Felipe Contreras
1442c29d39 check-versions: fix variable
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2022-07-30 00:19:38 -05:00
Julien Cristau
dfa3ad5fca helper: adjust for hg 6.1
mercurial.util.url became mercurial.utils.urlutil.url in 5.8.
2022-03-28 22:48:55 +02:00
Mark Nauwelaerts
ebd5bdb111 Release v1.0.3.2 2022-02-23 23:16:12 +01:00
Paul Wise
00ac711fb2 Fix syntax error caused by extra semicolon
Fixes: commit 4d38bff053
2022-02-23 23:15:30 +01:00
Mark Nauwelaerts
aadc899982 Release v1.0.3.1 2022-02-22 22:00:48 +01:00
Paul Wise
4d38bff053 Fail the build when Python with Mercurial is not available 2022-02-22 21:58:51 +01:00
Paul Wise
a8cd6a92b3 Do not overwrite found python executable with 'python' 2022-02-22 21:58:51 +01:00
Paul Wise
a08ad9d2b4 Add an option to test the pre-installed scripts
This is useful for distros like Debian that do tests on installed packages.

See-also: https://ci.debian.net/
2022-02-22 21:58:51 +01:00
Mark Nauwelaerts
8c08b6de21 Release v1.0.3 2022-02-21 22:55:11 +01:00
Mark Nauwelaerts
949345fb11 test: drop check on default
... since default branch is updated semi-random (implementation defined) from
the last non-branch push.

Fixes mnauw/git-remote-hg#48
2022-02-20 15:38:54 +01:00
Mark Nauwelaerts
0d49f75131 test: additional basic configuration 2022-02-20 15:38:54 +01:00
Mark Nauwelaerts
7159e4a030 Ensure URL encoding of tilde when sanitizing refname
Fixes mnauw/git-remote-hg#44
2021-08-28 20:29:59 +02:00
Paul Wise
cdcd70b453 Tell git to ignore the Python setuptools build/dist/metadata dirs
This helps ensure these don't get committed by accident and
helps prevent git interacting with them in other ways.
2021-08-22 21:14:24 +02:00
Paul Wise
f5c38f3a59 Run Python scripts under the chosen version
The Python scripts have unversioned Python shebangs so tests will
fail if the chosen Python version is not unversioned Python.

Copy the scripts to tmp dirs and change the shebang to the chosen Python.

Also prevent sharness from adding the unversioned Python scripts to PATH.
2021-04-05 13:27:00 +02:00
Paul Wise
3b11156e69 Detect which Python version is available and run tests using it
Allow overriding the Python version.

Use importing the mercurial module as the test rather than just python,
and merge the python and mercurial module skipping into one test for both
since the mercurial module has to work under the chosen python version.
2021-04-05 13:27:00 +02:00
Paul Wise
afc1f3a2c2 Try to install Python scripts with versioned Python shebangs
Allow overriding the Python version.

The Python setuptools based build system already modifies shebangs.

The Python scripts have unversioned Python shebangs so they
will fail if an unversioned Python is not provided by the OS.

The Debian bullseye release will not have an unversioned Python by default.

Avoid make pattern rules and shell functions since they are not portable.
2021-04-05 13:27:00 +02:00
Paul Wise
e596a5f457 Add missing line ending at EOF 2021-04-05 13:25:36 +02:00
Paul Wise
ec654d4682 Be more flexible about the path to sharness
Some folks might want to run a different version.

Check all the common installation paths and
support using a custom path to sharness.
2021-04-03 10:29:48 +02:00
Paul Wise
7913920a97 Create temporary directories dynamically
This avoids creating them in /tmp when another tmp dir was chosen.
2021-04-03 10:03:10 +02:00
Paul Wise
da60201ae3 Clean up temporary directories on exit 2021-04-03 10:03:10 +02:00
Paul Wise
704869df29 Install git-hg-helper when using the make build system
It is used by git-remote-hg and the Python
also setuptools build system installs it.
2021-04-03 10:02:49 +02:00
Paul Wise
5769e965eb Expect success for the main pull tags test
The git bug that caused the switch to unstable has been fixed.

This reverts commit a5dfc9025b.
2021-04-03 10:01:35 +02:00
Paul Wise
1ee28bd233 Use a compatible umask for the executable bit preservation test
More restrictive umasks like 027 will cause the test to fail.

Ubuntu 21.04 will change the default umask to 027.
2021-04-03 10:00:58 +02:00
Paul Wise
1796289df3 Remove unused Python imports in the setuptools build system
Suggested-by: vulture
2021-04-03 10:00:18 +02:00
Mark Nauwelaerts
929ae262f5 Release v1.0.2.1 2020-08-03 21:07:22 +02:00
Mark Nauwelaerts
4328aa1c19 setup: add python3 as supported version 2020-08-03 21:07:22 +02:00
Mark Nauwelaerts
919678be4a Release v1.0.2 2020-07-19 19:18:17 +02:00
Mark Nauwelaerts
ac8f659620 Really use generic python reference in shebang 2020-07-19 19:08:31 +02:00
Mark Nauwelaerts
28ed63b707 test: use generic python reference rather than python2 2020-06-12 14:00:17 +02:00
Mark Nauwelaerts
dc91c58e1c Use generic python reference in shebang 2020-06-12 14:00:17 +02:00
Mark Nauwelaerts
46178f546a test: use a legacy mode for hg-git test 2020-06-12 13:42:19 +02:00
Mark Nauwelaerts
4c0e8e6439 Make tag writing more robust 2020-06-12 13:42:19 +02:00
Mark Nauwelaerts
59b5a8c848 Make python2/3 compatible
See mnauw/git-remote-hg#27
2020-06-12 13:26:45 +02:00
Mark Nauwelaerts
be2445963b test: align order of options to stable ArgumentParser expectation 2020-06-12 13:20:25 +02:00
Mark Nauwelaerts
8b4bfe7e87 test: drop check on master in push mode
... since master is picked semi-random (implementation defined) in case
of multiple default branch tips

This mainly affects push mode since a preceding command succeeds
partially (and therefore affect the random), whereas the preceding fails
completely in non-push mode.
2020-06-12 13:20:25 +02:00
Mark Nauwelaerts
741b440fcc Apply url encoding for additional refname sanitizing
Fixes mnauw/git-remote-hg#33
2020-06-12 13:20:25 +02:00
Mark Nauwelaerts
03b1ac9845 Correctly check for valid revision
Fixes mnauw/git-remote-hg#32
2020-06-12 13:20:25 +02:00
Mark Nauwelaerts
f3a8546406 Merge branch 'felipec'
Integrate changes from felipec where appropriate and still relevant.
2020-06-01 13:02:48 +02:00
Mark Nauwelaerts
ccc9e55b7e Merge remote-tracking branch 'felipec/master' into felipec
These remaining changes have been mostly superseded
(e.g. revwalk iso gitrange, no more fetch-first error).
2020-06-01 12:58:26 +02:00
Mark Nauwelaerts
b516aa9326 Merge commit 'b3cd' into felipec
These changes can be merged with limited to none conflict resolution.
2020-06-01 12:57:26 +02:00
Mark Nauwelaerts
08626200d0 Merge commit '7fb9' into felipec
An unattributed variation of existing commits that can be discarded.
2020-06-01 12:54:44 +02:00
Mark Nauwelaerts
b60eb47173 Merge commit 'fad59f' into felipec
These changes can be merged with limited to none conflict resolution.
2020-06-01 12:52:41 +02:00
Mark Nauwelaerts
76162ce148 Merge commit '4d33' into felipec
These changes are unattributed ports of existing fixes and can as such
mostly be discarded.
2020-06-01 11:53:36 +02:00
Mark Nauwelaerts
7ae03f7640 Merge commit '5cc27' into felipec
These changes can be merged with limited to none conflict resolution.
2020-06-01 11:38:52 +02:00
Mark Nauwelaerts
95da53badd test: adjust push force to push mode behavior 2020-06-01 11:12:50 +02:00
Mark Nauwelaerts
a0608664ca Remove commented remnant 2020-06-01 11:12:34 +02:00
David Turner
9d6d135855 fix race fix on local repos 2019-08-03 21:23:51 +02:00
David Turner
60a6c7b36d Fix a race condition
If new heads are created on a remote http repo after we pull but
before we request branch heads, we'll try to read a head that we don't
actually have locally.  To fix this, we request the branchmap before
fetching, and only fetch the heads that we just learned about.
2019-07-22 21:22:09 +02:00
Felipe Contreras
74d1aa14ac gitrange(): general refactoring
To make the code more readable.

No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-20 14:39:36 -05:00
Felipe Contreras
1d85449b0b gitrange(): always check negatives first
Also, always add the parents as negatives.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-20 14:36:21 -05:00
Felipe Contreras
fe8b8c1a61 gitrange(): store parentrevs method
By calling the methods through a variable the code is significantly
faster.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-20 14:36:07 -05:00
Felipe Contreras
510441bba9 gitrange(): add a == b check
Otherwise we return the whole repository. Thanks to the marks we don't
actually export it, but there's no need to return so many revs.

Reported-by: Mark Nauwelaerts <mnauw@users.sourceforge.net>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-20 14:35:45 -05:00
Mark Nauwelaerts
fa3484e08b Find outgoing changesets earlier
This way we can find if we actually need to push something.

Recent versions of Mercurial already handle this correctly, but let's
check ourselves to make sure, and make it work with all versions.

Rewritten-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-19 10:12:05 -05:00
Mark Nauwelaerts
d1544e2ccd test: pushing a bookmark without changesets
This works in recent versions of Mercurial.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-19 09:58:21 -05:00
Felipe Contreras
153a216f47 test: main: cleanup big push fetch first
In order to use setup_big_push().

No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 19:24:19 -05:00
Felipe Contreras
b3cdbe8e96 Allow --force --dry-run
No reason for it not to work.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 18:50:52 -05:00
Felipe Contreras
d11509cab7 test: main: trivial cleanup
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 18:45:03 -05:00
Felipe Contreras
4d01165b1b test: main: fix check_push() bug
We were not checking the kind correctly. Add a new case switch to avoid
these issues.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 18:18:00 -05:00
Felipe Contreras
a030d603ac test: main: cleanup check_push()
Return immediately after a failure.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 18:11:05 -05:00
Felipe Contreras
3d4a5a6d7e Trivial cleanup
By adding a helper function the code is more understandable.

No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 15:22:09 -05:00
Felipe Contreras
7fb9d9b642 Load global UI confguration
Since 4.1 there's a separate function for that.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-18 15:06:39 -05:00
Felipe Contreras
fad59f53eb Refactor timezone functions
Split them into hours and minutes, and use divmod() to make them more
readable.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-05 03:17:39 -05:00
Oliver Stueker
e17e147fb1 Fix timezone issue with negative offsets
The current code miscalculates the time-zone offsets for time zones that don't
have a full-hour offset and are located west of UTC (e.g. St. John's,
Newfoundland).

Basically it's caused because 33 // 10 == 3, but -33 // 10 != -3.

Take the example of St. John's (-0330). The correct integer timezone should be
3.5 * 3600 (12600), however, since we are not checking for negative module
arithmetic, instead of calculating the timezone for (-3, -30), we are doing it
for (-4, 70), which would be OK... if we had hours of 100 minutes:

  -4 * 100 + 70 = -330

We could fix the code to use proper negative arithmetic (mod -100), but why
bother with the extra complexity? Let's just use absolute numbers and fix the
sign later.

This fixes issue #48.

Commit message written by Felipe Contreras.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-05 03:12:47 -05:00
Felipe Contreras
4878023a8b Add helper for hg timezone
No functional changes.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 15:30:38 -05:00
Oliver Stueker
0dfae24d21 test: add test for issue with negative offsets
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 15:30:36 -05:00
Felipe Contreras
c7dbb5612b Add timezone bidirectionality test
Oliver Stueker pointed out correctly that there is an issue with the way
we handle negative timestamps that don't have a full hour offset.

This test shows that.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 15:28:35 -05:00
Felipe Contreras
cc4e5659d9 Merge branch 'check-versions'
* check-versions:
  travis: use check-versions tool
  check-versions: add hack for hg-git 0.8.x
  Add tool to run tests on many versions
2019-06-04 04:02:38 -05:00
Felipe Contreras
2c993b3433 travis: use check-versions tool
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 04:02:12 -05:00
Felipe Contreras
4944a384cd check-versions: add hack for hg-git 0.8.x
They made a mistake and broke bidirectionality when debugextrainmessage
is used.

The upstream report:

  https://bitbucket.org/durin42/hg-git/issues/281/

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 04:02:12 -05:00
Felipe Contreras
f29c42c645 Add tool to run tests on many versions
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 04:02:12 -05:00
Felipe Contreras
7b7c65f72d README: remove old limitations
They work now.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 04:02:06 -05:00
Felipe Contreras
cee3ed7c00 travis: add pip cache
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 00:56:41 -05:00
Felipe Contreras
01c9a981c7 travis: install latest released version of hg
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 00:18:18 -05:00
Felipe Contreras
d0a5888580 travis: update Mercurial versions
And general cleanups.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-04 00:12:47 -05:00
Felipe Contreras
a5dfc9025b test: mark a regression in Git
The issue is reported, and a proposed fix has been sent:

  https://marc.info/?l=git&m=155961441427321

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 21:32:05 -05:00
Felipe Contreras
4d337cff06 Don't catch all exceptions in export_ref()
Just in case.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
5cc271ef18 test: hggit: add simple file rename test
The Hg-Git project has put a lot of emphasis on file renaming, better
check for that explicitly, even though we are already testing that.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
c8fff2cd06 Use changelog.isancestorrev()
The old changelog.descendant() is deprecated in 4.7, gone in 4.8.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
c95fba3c18 Don't call repo[tag] directly
Deprecated in 4.6, gone in 4.7.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
aaef56a2a3 Use marks.applychange()
Since 4.3 bookmarks are updated with applychanges() and since 4.6
anything else is deprecated.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
a16c69a99c Refactor updatebookmarks()
Also, use the proper lock, even for older versions.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
00e95fd8df Call node.rev() instead of int(node)
The int(node) method has been removed in 4.6.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
5bf7aad6e3 Fix memfilectx() params
These changed again in 4.5.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
9b8e0ec2c0 Refactor memfilectx() method
It's getting hairy.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
b309562574 Use makechangegroup()
Since 4.4 we have yet another way to push revisions.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
e25d3d78cd Use repo.vfs() instead of repo.opener()
The method() opener has been a link to vfs() since a long time, and it's
now removed in 4.3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
ed5a70706a Fix getchangegroup() for 4.0
The arguments heads and common have been removed.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 20:23:18 -05:00
Felipe Contreras
0faf2c9189 Tell hg-git to be backwards compatible
Since version 0.7.0 hg-git stores extra information directly into the
commits, we don't support that, so we need to tell hg-git to do what it
always did: put the extra data in the message.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 19:54:48 -05:00
Felipe Contreras
ada49422a7 test: add test for annotated tags
So we make sure they keep working as expected.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 19:54:39 -05:00
Felipe Contreras
580cea0d31 Explicitly process tags
Normally tag commands come with a corresponding ref, but not since
Git v2.21.

It's not clear if Git's change is correct, but fix it our end anyway.

  fdf31b6369 (fast-export: ensure we export requested refs)

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 19:51:38 -05:00
Felipe Contreras
1f376e437f Revert "test: skip tests with broken hg-git compatibility"
We need to fix the compatibility.

This reverts commit 29a0d8a0e3.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 19:51:35 -05:00
Felipe Contreras
4108665799 Add version check for filelog creation
The functions are only present in 3.2. Older versions don't need this
code.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 19:49:54 -05:00
Felipe Contreras
fc28115a53 Avoid ManifestLookupError
In versions older than 2.6 ManifestLookupError doesn't exist.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 19:49:08 -05:00
Felipe Contreras
e3009683f8 test: add missing &&s
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 14:55:25 -05:00
Felipe Contreras
54cec85f94 test: update expected result
It seems these work since Git v2.0.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 14:55:20 -05:00
Felipe Contreras
5ad322c54d Merge branch 'sharness-output-dir'
* sharness-output-dir:
  test: sharness: add support for output directory
2019-06-03 14:54:51 -05:00
Felipe Contreras
13bbc8a342 test: sharness: add support for output directory
I don't know why this was removed from Git's version.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 14:54:44 -05:00
Felipe Contreras
673b50d3f4 test: update to sharness 1.1
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2019-06-03 14:54:29 -05:00
Mark Nauwelaerts
35ecb45fda Tweak hg to git ref name translation
Fixes mnauw/git-remote-hg#26
2019-05-19 13:01:59 +02:00
Mark Nauwelaerts
1456e68129 Really strip prefix to ensure a valid package version 2019-04-28 14:32:42 +02:00
Mark Nauwelaerts
de95133416 Release v1.0.1 2019-04-27 15:08:20 +02:00
Mark Nauwelaerts
e0b752be8f Move release version management to make stage
... to ensure setup.py does not trip some later time.

Fixes mnauw/git-remote-hg#25
2019-04-27 15:08:20 +02:00
native-api
f050de1bcc Additional installation step in Windows
fixes https://github.com/mnauw/git-remote-hg/issues/23
2019-03-19 20:41:21 +01:00
Mark Nauwelaerts
0bf3db826b Handle platform dependency in atomic file renaming 2019-01-06 15:51:42 +01:00
Mark Nauwelaerts
3698638e98 Always pass forward slash to git
Fixes mnauw/git-remote-hg#22
2019-01-06 15:51:42 +01:00
Mark Nauwelaerts
765f9ae287 Add python pip packaging
Fixes mnauw/git-remote-hg#13
2018-10-14 16:27:51 +02:00
Mark Nauwelaerts
5ddcdd33ec Adjust to Mercurial 4.7 wrt deprecated revlog method 2018-09-09 12:08:29 +02:00
Mark Nauwelaerts
435373ee83 Adjust to Mercurial 4.7 wrt more restricted changectx API
Fixes mnauw/git-remote-hg#18
2018-09-09 12:08:26 +02:00
Mark Nauwelaerts
5e96683f67 Adjust to Mercurial 4.6 wrt revision numbers
... as modified in 38f4805020437f126f5c1c8f41d78445f9ab6547

Fixes mnauw/git-remote-hg#16
2018-05-14 21:40:37 +02:00
Mark Nauwelaerts
144f48df44 Adjust to Mercurial 4.6 wrt bookmarks
... as modified in cd23423029287e299d65bbece497ff09a2a673f4
2018-05-14 21:40:37 +02:00
Mark Nauwelaerts
ad36a25064 helper: adjust to Mercurial 4.6 wrt subrepo helper functions
... now in a separate module as of 55e8efa2451a0999b56978e471dc31dc8066a0fb
2018-05-14 21:27:40 +02:00
Mark Nauwelaerts
679e016943 Adjust to modified internals of Mercurial 4.5
Fixes mnauw/git-remote-hg#12
2018-02-07 18:47:18 +01:00
Mark Nauwelaerts
9f6c541a2c test: tweak and clarify copy-rename test
... to align it with current git's more restricted behavior
2017-12-03 14:29:27 +01:00
Mark Nauwelaerts
476ffcbde0 test: adjust to recent git-fast-export which only detects exact copy
Fixes mnauw/git-remote-hg#11
2017-11-28 20:50:18 +01:00
Mark Nauwelaerts
76be528c0d Optionally ignore some remote Mercurial revision names
... in particular when these would otherwise map to unsupported refnames.

Fixes mnauw/git-remote-hg#10
2017-11-27 20:57:19 +01:00
Mark Nauwelaerts
6c2f4d8ff4 Adjust to recent Mercurial API in pushing to remote
Fixes mnauw/git-remote-hg#9
2017-11-11 17:23:46 +01:00
Mark Nauwelaerts
e9c37f78d8 test: adjust hg subrepo configuration 2017-11-11 17:23:46 +01:00
Mark Nauwelaerts
dfa6910cab Adjust to recent Mercurial API in hg-git mode tag handling 2017-09-21 13:15:20 +02:00
Mark Nauwelaerts
2ab9ae9073 Use ui.ui.load() only if available 2017-09-18 21:24:22 +02:00
Beren Minor
f21923b052 Add info about hg repos used as git submodules 2017-09-18 20:24:24 +02:00
Beren Minor
45866dbeba Use ui.ui.load() to create a new ui which loads the global and user hg config 2017-09-18 13:47:01 +02:00
Renaud Casenave-Péré
eaa9361ab0 Fix README formatting 2017-08-09 19:00:41 +02:00
Mark Nauwelaerts
f0e4c95bf5 Add test for importing multiple independent histories
Based on reproduction steps provided by Adam Bliss.
2017-05-01 14:51:19 +02:00
David Turner
e467b22dd3 Fix obscure bug with multiple independent histories
If you have a repository with multiple independent histories (perhaps
that get merged later), under some circumstances revision 0 can get
imported *after* some other revision.  "Independent histories" are those
that start from different zero-parent commits.  I have thus far failed to
get a local reproduction on this, in part because I don't understand
how git-remote-hg choses the order in which to import branches.  But
we did notice this in our production system.

If revision 0 is imported late, a reset would not be issued, and it would
be wrongly re-parented on top of whatever previous history existed, instead
of being a root-level commit.

Fix this by always issuing a reset for a parentless commit, even on
revision 0.
2017-04-21 16:47:36 -04:00
Mark Nauwelaerts
40c9eafcc9 Fix corner case version calculation 2017-03-13 20:53:44 +01:00
Mark Nauwelaerts
0bfbc0da4b Merge pull request #4 from novalis/dturner/do-not-mangle-quotes
Optionally don't mangle git usernames with quotes
2016-12-06 22:02:02 +01:00
David Turner
a1ca279d92 Optionally don't mangle git usernames with quotes
By default, for backwards compatibility with earlier versions,
git-remote-hg removes quotation marks from git usernames
(e.g. 'Raffaello "Raphael" Sanzio da Urbino <raphael@example.com>'
would become 'Raffaello Raphael Sanzio da Urbino
<raphael@example.com>').  This breaks round-trip compatibility; a git
commit by an author with quotes would become an hg commit without,
and if re-imported into git, would get a different SHA1.

To restore round-trip compatibility (at the cost of backwards
compatibility with commits converted by older versions of
git-remote-hg), add an option 'remote-hg.remove-username-quotes'. This
option defaults to true (for backwards compatibility).
2016-12-05 16:08:01 -05:00
David Turner
e19dd84571 hack for submodules
A complete solution for submodules might be to convert them to hg
subrepositories.  But this would, in the general case, be quite
difficult -- for instance, local copies of all historical submodule
commits might not be available, and repositories might have moved
around.

It's better to do the conversion in some understandable way than to
crash with a weird error message, so let's do that.
2016-11-29 16:41:21 -05:00
Mark Nauwelaerts
1d94ba2d42 Add compatibility for Mercurial v4.0
Fixes felipec/git-remote-hg#66
2016-11-22 19:54:09 +01:00
Mark Nauwelaerts
85b585b824 Make unit test for executable rename slightly more resilient. 2016-11-15 20:51:21 +01:00
David Turner
e8c88c70d9 Fix mode setting in the case of moved executable files 2016-11-14 18:13:56 -05:00
Mark Nauwelaerts
a35f93cbc1 Fix duplication typos in marks file migration.
Fixes mnauw/git-remote-hg#1
2016-11-12 16:18:04 +01:00
Mark Nauwelaerts
a59e1246a2 Refactor updating of notes upon fetch and push 2016-10-18 21:32:26 +02:00
Mark Nauwelaerts
cbbbaddc41 Support using shared marks files for all remotes
... which essentially track the shared bag of revisions that
the shared proxy repo constitutes.
2016-10-18 21:32:19 +02:00
Mark Nauwelaerts
5d429d2da1 Refactor all marks file path access through common variable 2016-10-18 21:32:11 +02:00
Mark Nauwelaerts
94bb2488e8 Fix comment typo 2016-10-18 21:32:04 +02:00
Mark Nauwelaerts
e759d5232d README: clarify documentation on strip recovery 2016-10-18 21:31:57 +02:00
Mark Nauwelaerts
af96a84c98 Do not actually delete branch in case of dry-run 2016-10-18 21:31:48 +02:00
Mark Nauwelaerts
2ce962c5ab Really delete the private branch ref when deleting a branch 2016-10-18 21:31:34 +02:00
Mark Nauwelaerts
8ac5532eb1 Add to copyright for recent changes
... as there have been quite some by now.
2016-10-18 21:18:21 +02:00
Mark Nauwelaerts
9528e757d3 git-hg-helper: use an absolute path in sharedpath to refer to shared repo
... as some Mercurial commands are otherwise confused, e.g. thg.
2016-08-20 11:05:54 +02:00
Mark Nauwelaerts
628c45a4a9 Avoid bytecode generation when importing 2016-08-20 11:05:54 +02:00
Mark Nauwelaerts
55689eb0a8 git-hg-helper: refactor importing sibling module 2016-08-20 11:05:54 +02:00
Mark Nauwelaerts
7be9bf3db4 git-hg-helper: ensure proper directory tracking 2016-08-20 11:05:49 +02:00
Mark Nauwelaerts
20e923cf91 git-hg-helper: gc: resurrect Mercurial repo revision checking 2016-08-20 11:05:49 +02:00
Mark Nauwelaerts
a7ea76788c README: update documentation with latest changes on fetching 2016-08-13 14:28:04 +02:00
Mark Nauwelaerts
5999a10519 git-hg-helper: repurpose marks subcommand to gc subcommand 2016-08-13 14:28:01 +02:00
Mark Nauwelaerts
0853bc0230 Tips metadata is now obsolete on fetch as well as push
... so discard it altogether when reading marks.
All this also removes fetch-first error which is either no error at all or
is either really a non-fast-forward error.
2016-08-13 14:28:00 +02:00
Mark Nauwelaerts
b3fccddd9f Transform gitrange into a more effective revwalk
Fixes felipec/git-remote-hg#14
Fixes felipec/git-remote-hg#26
2016-08-13 14:27:57 +02:00
Mark Nauwelaerts
7f99aa2565 Ensure sane ratio in progress reporting 2016-08-13 14:27:54 +02:00
Mark Nauwelaerts
63c742e4a6 Add warning about disabling capability_push mode
... as the old mode is not so safe and on its way to deprecation.
2016-08-13 14:27:52 +02:00
Mark Nauwelaerts
6cff0327aa Always update notes on push
... at least in the sane capability_push mode.
Remove documentation on obsolete push-updates-notes setting.
2016-08-13 14:27:52 +02:00
Mark Nauwelaerts
5acd0028b4 Ensure transaction safe notes update on push 2016-08-13 14:27:52 +02:00
Mark Nauwelaerts
4f910f65d9 Also still track notes HEAD during import
Fixes felipec/git-remote-hg#58
2016-08-13 14:27:45 +02:00
Mark Nauwelaerts
7d82847d52 README: add documentation on subrepo support 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
37cd2f24ac git-hg-helper: add support for subrepo management
See felipec/git-remote-hg#1
2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
585e36edb9 README: add documentation on additional features such as git-hg-helper 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
dd08e25665 doc: extend manpage with additional config settings 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
5905eb2231 Make a push optionally update notes as well
... as configured by remote-hg.push-updates-notes setting.
2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
ebdd2f32ab Add support for automagic hg revision identification and pushing 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
f8709175bf Separate head checking and revision pushing
Also remove some superfluous function parameters and add another one
to avoid using global var.
2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
38741e0bbf Add git-hg-helper 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
e2f68018cd Allow using git-remote-hg as module 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
e62984edde README: add hiding of refs/hg 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
7b53adef7b Avoid refs/hg clutter; keep private implementation refs really private 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
858ca2c68a README: explain effects of capability push implementation 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
093cb8ba94 README: some obligatory fork adjustments 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
cd742bee40 doc: extend manpage with config settings and some technical background 2016-08-01 14:57:01 +02:00
Mark Nauwelaerts
1d0c78eebc test: expect dry-run push test to pass now 2016-08-01 14:57:00 +02:00
Mark Nauwelaerts
8e81bc8515 Add source:dest push refspec support 2016-08-01 14:57:00 +02:00
Mark Nauwelaerts
bd2e030cb0 Add remote bookmark delete support 2016-08-01 14:57:00 +02:00
Mark Nauwelaerts
410e0d74ec test: add test for rename/copy detection 2016-08-01 14:57:00 +02:00
Mark Nauwelaerts
93dd913590 Implement remote-helper push capability
Push capability is used depending on remote-hg.capability-push setting and ...
* handles dry-run properly,
* passes copy and rename information onto Mercurial

Fixes felipec/git-remote-hg#61
2016-08-01 14:56:42 +02:00
Mark Nauwelaerts
418af65bf0 Support processing git-fast-export's filecopy and filerename 2016-08-01 14:15:47 +02:00
Mark Nauwelaerts
d7db83bd2c Handle pushing bookmarks without pushing changesets
Also prevent errors when trying to push no changesets to a peer, which some
combinations of versions and extensions do not handle well;
see e.g. as in felipec/git-remote-hg#32 and felipec/git-remote-hg#22
2016-08-01 14:12:09 +02:00
Mark Nauwelaerts
3ea455e7e7 test: add failing test for pushing a bookmark without changesets 2016-08-01 12:21:30 +02:00
Mark Nauwelaerts
fd210eb002 Also ensure 2-way sync of remote bookmarks to proxy
... rather than only adding remote ones locally and never deleting.
In particular, makes fetch --prune work.

Fixes felipec/git-remote-hg#15
2016-08-01 12:21:30 +02:00
Mark Nauwelaerts
b852ee18b2 Simplify calculation of revision range to be fetched.
Fixes felipec/git-remote-hg#14
2016-08-01 12:21:30 +02:00
Mark Nauwelaerts
c3f02d39ad Add notes based on current notes ref
Fixes felipec/git-remote-hg#58
2016-08-01 12:21:25 +02:00
Felipe Contreras
822c6e4b03 Avoid deprecated bookmarks.write()
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-17 21:26:18 -05:00
Felipe Contreras
b6e9475918 readme: mention Mercurial dependency
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 23:37:08 -05:00
Lars Noschinski
517ceb91ac Fix import of broken committers
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 22:44:49 -05:00
Felipe Contreras
114804f0cb travis: add more Mercurial versions
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 22:29:50 -05:00
Felipe Contreras
b022367aef test: temporarily disable hg-git tests
They work, but they need too many changes in different packages.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 22:29:50 -05:00
Felipe Contreras
18626d346f Revert "test: use C.UTF-8 locale in tests"
This reverts commit f53a8653ab.

It turns out Debian and Fedora do provide the C.UTF-8 locale, but other
distributions don't.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 22:29:50 -05:00
Felipe Contreras
b81ec14c2e Improve hg-git compatibility
Recent versions of Mercurial check if a filectx is the same as the
parents, and avoid creating a new filelog. This is what we want, but
hg-git doesn't do that.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 22:29:50 -05:00
Felipe Contreras
1e279075dc Add compatibility for Mercurial v3.2
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 22:29:50 -05:00
Felipe Contreras
02a0a59a4b travis: force version of hg-git
The latest that works.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2016-05-16 17:56:25 -05:00
Felipe Contreras
185852eac4 test: cleanup hg-git test
We don't need hgext.bookmarks since a long long time (ever).

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-06-03 06:00:02 -05:00
Felipe Contreras
29a0d8a0e3 test: skip tests with broken hg-git compatibility
https://bitbucket.org/durin42/hg-git/issue/115/

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-06-02 18:42:17 -05:00
Felipe Contreras
aa528c9649 Fix memfilectx API change
It will change in 3.1.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-06-02 17:49:56 -05:00
Felipe Contreras
018aa4753b Improve version parsing
Development versions have extra stuff in the form of
'version+distance-id'.

Let's assume we are already in the next major version when in
development.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-06-02 17:49:29 -05:00
Felipe Contreras
f173208406 build: don't install docs by default
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-31 15:58:33 -05:00
Felipe Contreras
e7df347fab readme: fix not about v2.0
It didn't get in.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-31 15:49:28 -05:00
Brian Gernhardt
0de8aa91f4 build: avoid non-portable install -D
BSD install doesn't understand the -D option. Use a separate install
command to create the directory (with the -d option) before installing
the file.

Signed-off-by: Brian Gernhardt <brian@gernhardtsoftware.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-31 15:41:28 -05:00
Paul Wise
22d9794c11 test: add compatibility with Debian hg-git package
Debian has named the hggit python module as hgext.git.

Signed-off-by: Paul Wise <pabs3@bonedaddy.net>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-30 17:37:01 -05:00
Paul Wise
f53a8653ab test: use C.UTF-8 locale in tests
The en_US.UTF-8 locale is not guaranteed to exist, and if it doesn't,
several tests fail.

Signed-off-by: Paul Wise <pabs3@bonedaddy.net>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-30 17:37:01 -05:00
Paul Wise
b4c63539f2 Ignore the generated manual page
Signed-off-by: Paul Wise <pabs3@bonedaddy.net>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-30 17:37:01 -05:00
Paul Wise
38070007aa build: general improvements
Allow customising the bin and manual page dirs.

Signed-off-by: Paul Wise <pabs3@bonedaddy.net>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-30 17:37:01 -05:00
Felipe Contreras
fadd5f698b test: improve test locations
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-22 22:09:28 -05:00
Felipe Contreras
1eb8fa4805 readme: add contributing section
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-13 14:26:45 -05:00
Felipe Contreras
19f31c1c84 doc: add help for sending patches
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-13 14:26:32 -05:00
Felipe Contreras
ff221de459 Split multiple import lines
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-10 23:54:33 -05:00
Felipe Contreras
179fefda96 More pep8 fixes
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-10 23:49:49 -05:00
Felipe Contreras
c226ba3904 remote-hg,bzr: conform more to pep8
Reported-by: William Giokas <1007380@gmail.com>

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-10 01:01:20 -05:00
Felipe Contreras
776e36c147 build: fix install location
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 10:29:52 -05:00
Felipe Contreras
5b6d5283cb Use python2 instead of python
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 09:11:14 -05:00
Felipe Contreras
5738ee42d8 test: add missing redirection
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 09:10:57 -05:00
Felipe Contreras
1d27390dd0 readme: fix link location
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 09:09:16 -05:00
Felipe Contreras
cad5c95465 travis: add initial configuration
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 09:04:31 -05:00
Felipe Contreras
259838a342 test: fix redirection style
To be sane, a redirection operation has to have spaces, like any binary
operand: 'a > b'.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:55:51 -05:00
Felipe Contreras
55bbd81a75 test: trivial style cleanups
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:49:30 -05:00
Felipe Contreras
8db5b9a537 Add support for hg v3.0
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
bbc4009acf test: trivial cleanups and fixes
There was a broken && chain, and cat is simpler than echo in a subshell.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
c84feb364b test: dd file operation tests
Inspired by gitifyhg.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
990152c0c8 Add more tests
Inspired by the tests in gitifyhg.

One test is failing, but that's because of a limitation of
remote-helpers.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
6ba42cdf98 Simplify hg-git regex
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
ef00e40d7c remote-hg: make sure we omit multiple heads
We want to ignore secondary heads, otherwise we will import revisions
that won't have any ref pointing to them and might eventually be pruned,
which would cause problems with the synchronization of marks.

This can only be expressed properly as '::b - ::a', but that's not
efficient, specially in older versions of Mercurial.
'ancestor(a,b)::b - ancestor(a,b)::a' might be better, but it's not
particularly pretty. Mercurial v3.0 will have a new 'only(b, a)' that
does the same, but that hasn't even been released yet. Either way all of
these require repo.revs() which is only available after Mercurial v2.1.

Also, we would need special considerations for when there's no base
revision (importing from root).

It's much better to implement our own function to get a range of
revisions.

The new gitrange() is inspired by Mercurial's revset.missingancestors().

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Max Horn
1c72617831 Do not fail on invalid bookmarks
Mercurial can have bookmarks pointing to "nullid" (the empty root
revision), while Git can not have references to it.

Warn the user about the invalid reference, and do not advertise these
bookmarks as head refs, but otherwise continue the import. In
particular, we still keep track of the fact that the remote repository
has a bookmark of the given name, in case the user wants to modify that
bookmark.

Reported-by: Antoine Pelisse <apelisse@gmail.com>
Signed-off-by: Max Horn <max@quendi.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Daniel Liew
184551c71d Use internal clone's hgrc
Use the hgrc configuration file in the internal mercurial repository in
addition to the other system wide hgrc files. This is done by using the
'ui' object from the 'repository' object which will have loaded the
repository hgrc file if it exists.

Signed-off-by: Dan Liew <delcypher@gmail.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
32d4f36f22 test: split into setup test
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
ccb3f13d69 Properly detect missing contexts
This can happen when there's a synchronization issue between marks-git
and marks-hg; a key is missing in marks-hg, and when we receive a reset
command the value of ctx basically comes from None.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:07 -05:00
Felipe Contreras
2958556bec Store marks only on success
Commit 2594a79 (remote-hg: fix bad state issue) originally introduced
this code in order to avoid synchronization issues while pushing,
because `git fast-export` might end up writing the marks before a crash
in the remote helper occurs.

However, the problem is in `git fast-export`; the marks should only be
written after both have finished successfully.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:06 -05:00
Felipe Contreras
4ea2fa76b3 Update to 'public' phase when pushing
This is what Mercurial does.

Reported-by: Nathan Palmer
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:06 -05:00
Felipe Contreras
84b8b482a4 Fix parsing of custom committer
Other tools use the 'committer' extra field differently, so let's make
the parsing more reliable and don't assume it's in a certain format.

Reported-by: Kevin Cox <kevincox@kevincox.ca>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:06 -05:00
Felipe Contreras
978314a4be Always normalize paths
Apparently Mercurial can have paths such as 'foo//bar', so normalize all
paths.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:43:06 -05:00
Felipe Contreras
51eabd4a17 doc: add manpage
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:41:57 -05:00
Felipe Contreras
98c3535c3f build: add install target
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:41:57 -05:00
Felipe Contreras
3abf376e9e Add README
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:36:33 -05:00
Felipe Contreras
0b71ca38e7 Reorganize tests
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
2014-05-09 08:33:07 -05:00
49 changed files with 8256 additions and 2529 deletions

44
.github/workflows/ci.yml vendored Normal file
View 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

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/build/
/dist/
/git_remote_hg.egg-info/

View File

@@ -1,6 +1,64 @@
all:
prefix := $(HOME)
bindir := $(prefix)/bin
mandir := $(prefix)/share/man/man1
all: build doc
build:
if [ -n "$$PYTHON" ] && "$$PYTHON" -c 'import mercurial' 2> /dev/null ; then \
: Use chosen Python version ; \
elif python3 -c 'import mercurial' 2> /dev/null ; then \
PYTHON=python3 ; \
elif python2 -c 'import mercurial' 2> /dev/null ; then \
PYTHON=python2 ; \
elif python -c 'import mercurial' 2> /dev/null ; then \
PYTHON=python ; \
else \
echo 'Python with Mercurial not available' >&2 ; \
exit 1 ; \
fi ; \
mkdir -p bin ; \
for s in git-remote-hg git-hg-helper ; do \
printf "%s\n" "#!/usr/bin/env $$PYTHON" > "bin/$$s" ; \
tail -n +2 "./$$s" >> "bin/$$s" ; \
chmod 755 "bin/$$s" ; \
touch -r "./$$s" "bin/$$s" ; \
done
doc: doc/git-remote-hg.1
test:
$(MAKE) -C test
$(MAKE) -C t
.PHONY: all test
doc/git-remote-hg.1: doc/git-remote-hg.txt
asciidoctor -d manpage -b manpage $<
clean:
$(RM) doc/git-remote-hg.1
$(RM) -r bin/
D = $(DESTDIR)
install: build
install -d -m 755 $(D)$(bindir)/
install -m 755 bin/git-remote-hg $(D)$(bindir)/git-remote-hg
install -m 755 bin/git-hg-helper $(D)$(bindir)/git-hg-helper
install-doc: doc
install -d -m 755 $(D)$(mandir)/
install -m 644 doc/git-remote-hg.1 $(D)$(mandir)/git-remote-hg.1
pypi:
version=`git describe --tags ${REV}` && \
sed -i "s/version = .*/version = '$$version'[1:]/" setup.py
-rm -rf dist build
python setup.py sdist bdist_wheel
pypi-upload:
twine upload dist/*
pypi-test:
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
.PHONY: all build test install install-doc clean pypy pypy-upload

446
README.asciidoc Normal file
View File

@@ -0,0 +1,446 @@
`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:
--------------------------------------
git clone "hg::http://selenic.com/repo/hello"
--------------------------------------
To enable this, simply add the `git-remote-hg` script anywhere in your `$PATH`:
--------------------------------------
wget https://raw.githubusercontent.com/mnauw/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg
chmod +x ~/bin/git-remote-hg
--------------------------------------
In Windows, you also need to put and an NTFS symbolic link named `python2.exe` somewhere
on your `$PATH` pointing to your Python 2 executable:
--------------------------------------
mklink <path to link> <path to python.exe>
--------------------------------------
That's it :)
Obviously you will need Mercurial installed.
****
At present, this "working copy"/fork <<add-features, adds the following features>>
(and I would prefer it is indeed rather a "working copy"
to be appropriately merged upstream):
* eliminates a number of <<limitations, limitations>> as mentioned below
* properly annotates copy/rename when pushing new commits to Mercurial
* adds a 'git-hg-helper' script than can aid in the git-hg interaction workflow
* provides enhanced bidirectional git-hg safety
* avoids clutter of `refs/hg/...` by keeping these implementation details really private
* more robust and efficient fetching, especially so when fetching or cloning from multiple
Mercurial clones which will only process changesets not yet fetched from elsewhere
(as opposed to processing everything all over again)
See sections below or sidemarked notes for more details.
****
== Configuration ==
If you want to see Mercurial revisions as Git commit notes:
--------------------------------------
% git config core.notesRef refs/notes/hg
--------------------------------------
If you are not interested in Mercurial permanent and global branches (aka.
commit labels):
--------------------------------------
% git config --global remote-hg.track-branches false
--------------------------------------
With this configuration, the 'branches/foo' refs won't appear.
If you want the equivalent of `hg clone --insecure`:
--------------------------------------
% git config --global remote-hg.insecure true
--------------------------------------
If you want `git-remote-hg` to be compatible with `hg-git`, and generate exactly
the same commits:
--------------------------------------
% git config --global remote-hg.hg-git-compat true
--------------------------------------
****
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, especially if
it's a big one. Otherwise lots of space will be wasted.
=== Pushing branches ===
To push a branch, you need to use the 'branches/' prefix:
--------------------------------------
% git checkout branches/next
# do stuff
% git push origin branches/next
--------------------------------------
All the pushed commits will receive the "next" Mercurial named branch.
*Note*: Make sure you don't have `remote-hg.track-branches` disabled.
=== Cloning HTTPS ===
The simplest way is to specify the user and password in the URL:
--------------------------------------
git clone hg::https://user:password@bitbucket.org/user/repo
--------------------------------------
You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]:
--------------------------------------
[auth]
bb.prefix = https://bitbucket.org/user/
bb.username = user
bb.password = password
--------------------------------------
Finally, you can also use the
https://pypi.org/project/mercurial_keyring[keyring extension].
=== Submodules ===
Hg repositories can be used as git submodule, but this requires to allow the hg procotol to be used by git submodule commands:
--------------------------------------
git config protocol.hg.allow always
--------------------------------------
Or adding manually the following to your git configuration file:
--------------------------------------
[protocol "hg"]
allow = always
--------------------------------------
This can be done per-repository, every time after a clone, or globally in the global .gitconfig (using the --global command-line option).
=== Caveats ===
The only major incompatibility is that Git octopus merges (a merge with more
than two parents) are not supported.
Mercurial branches and bookmarks have some limitations of Git branches: you
can't have both 'dev/feature' and 'dev' (as Git uses files and directories to
store them).
Multiple anonymous heads (which are useless anyway) are not supported: you
would only see the latest head.
Closed branches are not supported: they are not shown and you can't close or
reopen. Additionally in certain rare situations a synchronization issue can
occur (https://github.com/felipec/git/issues/65[Bug #65]).
[[limitations]]
Limitations of the remote-helpers' framework apply. In particular, these
commands don't work:
* `git push origin :branch-to-delete`
****
Another limitation is that if `git log` reports a rename, this will not survive
the push and Mercurial will not be aware of a rename (and similarly so for copy).
Though Mercurial would know about it if you *manually* ran `git-format-patch`
followed by a `hg apply -s`, which is not the nice way to go obviously.
Actually, scratch the limitations above ascribed to the remote-helpers framework.
They are not limitations of the framework, but are due to how the original
implementation of 'git-remote-hg' interacts with it.
Using the remote-helpers framework in only a slightly different way has none
of the above limitations. See the <<no-limitations, relevant section>>
below for more details.
****
== Other projects ==
There are other `git-remote-hg` projects out there, but this is the original,
which was distributed officially in the Git project.
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) ==
If interested in some of technical details behind this explanation, then also
see the relevant section in 'git-remote-hg' manpage. Otherwise, the general
idea is presented here.
More precisely and simply, the <<limitations, mentioned limitations>> are indeed
limitations of the `export` capability of
https://www.kernel.org/pub/software/scm/git/docs/gitremote-helpers.html[gitremote-helpers(1)]
framework. However, the framework also supports a `push` capability and when this
is used appropriately in the remote helper the aforementioned limitations do not apply.
In the case of `export` capability, git-core will internally invoke `git-fast-export`
and the helper will process this data and hand over generated changesets to Mercurial.
In the case of `push` capability, git informs the helper what (refs) should go where,
and the helper is free to ponder about this and take the required action, such as
to invoke `git-fast-export` itself (with suitable options) and process its output
the same way as before (and over to Mercurial).
And so;
* `git push origin :branch-to-delete` will delete the bookmark `branch-to-delete` on remote
* `git push --dry-run origin branch` will not touch the remote
(or any local state, except for local helper proxy repo)
* `git push origin old:new` will push `old` onto `new` in the remote
* `git push origin <history-with-copy/rename>` will push copy/rename aware Mercurial revisions
To tweak how 'git-remote-hg' decides on a copy/rename, use e.g:
--------------------------------------
% git config --global remote-hg.fast-export-options '-M -C -C'
--------------------------------------
[[add-features]]
== Additional Features ==
=== Miscellaneous Tweaks ===
Other than <<no-limitations, removing the limitations>> as mentioned above,
a number of issues (either so reported in
https://github.com/felipec/git-remote-hg/issues[issue tracking] or not) have been
addressed here, e.g. notes handling, `fetch --prune` support, correctly fetching
after a `strip` on remote repo, tracking remote changes to import (if any) in a
safe, robust and efficient way, etc. Some of these have been highlighted above.
For example, the `refs/hg/...` refs are really an implementation detail
that need not clutter up the (visible) ref space. So, in as much as they
are still relevant, these are now kept elsewhere out of sight.
If somehow your workflow relies on having these in the old place:
--------------------------------------
% git config --global remote-hg.show-private-refs true
--------------------------------------
More importantly, a significantly more efficient workflow is achieved using
one set of shared marks files for all remotes (which also forces a local repo
to use an internal proxy clone).
The practical consequence is that fetching from a newly added remote hg repo
does not require another (lengthy) complete import
(as the original clone) but will only fetch additional changesets (if any).
The same goes for subsequent fetching from any hg remote; what was fetched
and imported from some remote need not be imported again from another.
Operating in this shared mode also has the added advantage
of correctly pushing after a `strip` on a remote.
This shared-marks-files behaviour is the default on a fresh repo clone. It can
also be enabled on an existing one by the following setting.
--------------------------------------
% git config --global remote-hg.shared-marks true
--------------------------------------
Note, however, that one should then perform a fetch from each relevant remote
to fully complete the conversion (prior to subsequent pushing).
Some Mercurial names (of branches, bookmarks, tags) may not be a valid git
refname. See e.g. `man git-check-ref-format` for a rather involved set of rules.
Moreover, while a slash `/` is allowed, it is not supported to have both a `parent`
and `parent/child` branch (though only the latter is allowed). Even though
it is not quite (bidirectionally) safe, a (percentage) URL encoding
(with some additional twist) is performed to obtain sane git refnames, at least
so for most cases. If some nasty cases still slip through, then likely only
a few instances (out of a whole Mercurial repo) are
problematic. This could be handled by a single-branch clone and/or configuring
a suitable refspec. However, it might be more convenient to simply filter out a
few unimportant pesky cases, which can be done by configuring a regural
expression in following setting:
--------------------------------------
% git config remote-hg.ignore-name nasty/nested/name
--------------------------------------
Recall also that a config setting can be provided at clone time
(command line using `--config` option).
--------------------------------------
% git config --global remote-hg.remove-username-quotes false
--------------------------------------
By default, for backwards compatibility with earlier versions,
git-remote-hg removes quotation marks from git usernames
(e.g. 'Raffaello "Raphael" Sanzio da Urbino <raphael@example.com>'
would become 'Raffaello Raphael Sanzio da Urbino
<raphael@example.com>'). This breaks round-trip compatibility; a git
commit by an author with quotes would become an hg commit without,
and if re-imported into git, would get a different SHA1.
To restore round-trip compatibility (at the cost of backwards
compatibility with commits converted by older versions of
git-remote-hg), turn 'remote-hg.remove-username-quotes' off.
=== Helper Commands ===
Beyond that, a 'git-hg-helper' script has been added that can aid in the git-hg
interaction workflow with a number of subcommands that are not in the purview of
a remote helper. This is similar to e.g. 'git-svn' being a separate program
altogether. These subcommands
* provide conversion from a hg changeset id to a git commit hash, or vice versa
* provide consistency and cleanup maintenance on internal `git-remote-hg` metadata marks
* provide optimization of git marks of a fetch-only remote
See the helper script commands' help description for further details.
It should simply be installed (`$PATH` accessible) next to 'git-remote-hg'.
Following git alias is probably also convenient as it allows invoking the helper
as `git hg`:
--------------------------------------
% git config --global alias.hg '!git-hg-helper'
--------------------------------------
With that in place, running `git hg gc <remote>` after initial fetch from (large)
<remote> will save quite some space in the git marks file. Not to mention some time
each time it is loaded and saved again (upon fetch). If the remote is ever pushed
to, the marks file will similarly be squashed, but for a fetch-only <remote>
the aforementioned command will do. It may also be needed to run aforementioned
command after a `git gc` has been performed. You will notice the need
when `git-fast-import` or `git-fast-export` complain about not finding objects ;-)
In addition, the helper also provides support routines for `git-remote-hg` that
provide for increased (or at least safer) git-hg bidirectionality.
Before explaining how it helps, let's first elaborate on what is really
meant by the above _bidirectionality_ since it can be regarded in 2 directions.
From the git repo point of view, one can push to a hg repo and then fetch (or
clone) back to git. Or one could have fetched a changeset from some hg repo and
then push this back to (another) hg clone. So what happens in either case? In the
former case, from git to hg and then back, things work out ok whether or not in
hg-git compatibility mode. In the latter case, it is very likely (but
ultimately not guaranteed) that it works out in hg-git compatibility mode, and far
less likely otherwise.
Most approaches on bidirectionality try to go for the "mapping" way.
That is, find a way to map all Mercurial (meta)data somewhere into git;
in the commit message, or in non-standard ways in extra headers in commit objects
(e.g. the latest hg-git approach). The upside of this is that such a git repo can be
cloned to another git repo, and then one can push back into hg which will/should
turn out ok. The downside is setting up such a mapping in the first place,
avoiding the slightest error in translating authors, timestamps etc,
and maintaining all that whenever there is some Mercurial API/ABI breakage.
The approach here is to consider a typical git-hg interaction workflow and to
ensure simple/safe bidirectionality in such a setting. That is, you are (obviously)
in a situation having to deal with some Mercurial repo and quite probably
with various clones as well. The objective is to fetch from these repos/clones,
work in git and then push back. And in the latter case, one needs to make sure
that hg changesets from one hg clone end up *exactly* that way in another hg
clone (or the git-hg bridge usage might not be so appreciated). Such pushes are
probably not recommended workflow practice, but no accidents or issues should
arise from any push in these circumstances. There is less interest in this setting,
however, for (git-wise) cloning around the derived git repo.
Now, depending on your workflow and to ensure the above behaves well,
following setting can be enabled as preferred:
--------------------------------------
% git config --global remote-hg.check-hg-commits fail
% git config --global remote-hg.check-hg-commits push
--------------------------------------
If not set, the behaviour is as before; pushing a commit based on hg changeset
will again transform the latter into a new hg changeset which may or may not
match the original (as described above).
If set to `fail`, it will reject and abort the push.
If set to `push`, it will re-use the original changeset in a Mercurial native
way (rather than creating a new one). The latter guarantees the changeset ends
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) (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).
=== Mercurial Subrepository Support ===
Both Git and Mercurial support a submodule/subrepo system.
In case of Git, URLs are managed in `.gitmodules`, submodule state is tracked
in tree objects and only Git submodules are supported.
Mercurial manages URLs in `.hgsub`, records subrepo state in `.hgsubstate` and
supports Git, Mercurial and Subversion subrepos (at time of writing).
Merely the latter diversity in subrepo types shows that somehow mapping Mercurial
"natively" to git submodules is not quite evident. Moreover, while one might
conceivably devise such a mapping restricted to git and hg subrepos, any such would
seem error-prone and fraught with all sorts of tricky cases and inconvenient
workflow handling (innovative robust suggestions are welcome though ...)
So, rather than overtaking the plumbing and ending up with stuffed drain further on,
the approach here is (again) to keep it plain-and-simple. That is, provide some
git-ish look-and-feel helper script commands for setting up and manipulating
subrepos. And so (if the alias mentioned above has been defined), `git hg sub`
provides commands similar to `git submodule` that accomplish what is otherwise
taken care of by the Mercurial subrepo support.
The latter is obviously extended to be git-aware in that e.g. a Mercurial subrepo
is cloned as a git-hg subrepo and translation back-and-forth between hg changeset id
and git commit hash is also performed where needed. There is no support though
for Subversion subrepos.
As with the other commands, see the help description for the proper details,
but the following example session may clarify the principle:
--------------------------------------
% git clone hg::hgparentrepo
# bring in subrepos in proper location:
% git hg sub update
# do some work
% git pull --rebase origin
# update subrepo state:
% git hg sub update
# do work in subrepo and push
% ( cd subrepo && git push origin HEAD:master )
# fetch to update refs/notes/hg (or enable remote-hg.push-updates-notes)
% ( cd subrepo && git fetch origin )
# update .hgsubstate to subrepo HEAD:
% git hg sub upstate
% git add .hgsubstate
# add more, commit and push as intended
--------------------------------------
Note that the refspec `HEAD:master` is needed if working with detached `HEAD`
in subrepo, and that pushing such refspec is actually supported now in a git-hg subrepo
as explained <<no-limitations, earlier>>.
== Contributing ==
Please file an issue with some patches or a pull-request.

1
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
git-remote-hg.1

5
doc/SubmittingPatches Normal file
View File

@@ -0,0 +1,5 @@
Please send your patches using `git format-patch` to the mailing list:
git-fc@googlegroups.com.
Make sure all the tests pass by running `make test`, and if possible add a new
test to exercise the code you are submitting.

226
doc/git-remote-hg.txt Normal file
View File

@@ -0,0 +1,226 @@
git-remote-hg(1)
================
NAME
----
git-remote-hg - bidirectional bridge between Git and Mercurial
SYNOPSIS
--------
[verse]
'git clone' hg::<hg repository>
DESCRIPTION
-----------
This tool allows you to transparently clone, fetch and push to and from Mercurial
repositories as if they were Git ones.
To use it you simply need to use the "'hg::'" prefix when specifying a remote URL
(e.g. when cloning).
EXAMPLE
-------
------------
$ git clone hg::http://selenic.com/repo/hello
------------
CONFIGURATION
-------------
If you want to see Mercurial revisions as Git commit notes:
--------------------------------------
% git config core.notesRef refs/notes/hg
--------------------------------------
If you are not interested in Mercurial permanent and global branches (aka.
commit labels):
--------------------------------------
% git config --global remote-hg.track-branches false
--------------------------------------
With this configuration, the 'branches/foo' refs won't appear.
If you want the equivalent of `hg clone --insecure`:
--------------------------------------
% git config --global remote-hg.insecure true
--------------------------------------
If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly
the same commits:
--------------------------------------
% git config --global remote-hg.hg-git-compat true
--------------------------------------
If you would like (why?) the old behaviour (export capability)
where various limitations apply:
--------------------------------------
% git config --global remote-hg.capability-push false
--------------------------------------
In the new behaviour, performing a git push will make git search for and detect
file rename and copy and turn this into Mercurial commit metadata. To tweak how this
detection happens, e.g. have it search even more:
--------------------------------------
% git config --global remote-hg.fast-export-options '-M -C -C'
--------------------------------------
The default otherwise is simply `-M -C`. See also e.g.
https://www.kernel.org/pub/software/scm/git/docs/git-log.html[git-log(1) manpage]
for more details on the options used to tweak this.
As the old refs/hg/... are actually an implementation detail, they are now
maintained not so visibly. If that, however, would be preferred:
--------------------------------------
% git config --global remote-hg.show-private-refs true
--------------------------------------
Use of shared marks files is the default in a new repo, but can also be enabled
for an existing repo:
--------------------------------------
% git config --global remote-hg.shared-marks true
--------------------------------------
Note that one should perform a fetch from each remote to properly complete the
conversion to shared marks files.
Mercurial name(s) (of a branch or bookmark) that are not a valid git refname,
can be ignored by configuring a suitable regular expression, e.g. avoiding
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, especially if
it's a big one. Otherwise lots of space will be wasted.
The newest supported version of Mercurial is 6.2, the oldest one is 2.4.
Pushing branches
~~~~~~~~~~~~~~~~
To push a branch, you need to use the "branches/" prefix:
--------------------------------------
% git checkout branches/next
# do stuff
% git push origin branches/next
--------------------------------------
All the pushed commits will receive the "next" Mercurial named branch.
*Note*: Make sure you don't have +remote-hg.track-branches+ disabled.
Cloning HTTPS
~~~~~~~~~~~~~
The simplest way is to specify the user and password in the URL:
--------------------------------------
git clone hg::https://user:password@bitbucket.org/user/repo
--------------------------------------
You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]:
--------------------------------------
[auth]
bb.prefix = https://bitbucket.org/user/
bb.username = user
bb.password = password
--------------------------------------
Finally, you can also use the
https://pypi.org/project/mercurial_keyring[keyring extension].
CAVEATS
-------
The only major incompatibility is that Git octopus merges (a merge with more
than two parents) are not supported.
Mercurial branches and bookmarks have some limitations of Git branches: you
can't have both 'dev/feature' and 'dev' (as Git uses files and directories to
store them).
Multiple anonymous heads (which are useless anyway) are not supported: you
would only see the latest head.
Closed branches are not supported: they are not shown and you can't close or
reopen. Additionally in certain rare situations a synchronization issue can
occur (https://github.com/felipec/git/issues/65[Bug #65]).
TECHNICAL DISCUSSION
--------------------
As `git-remote-hg` is a developer tool after all, it might be interesting to know a
bit about what is going on behind the scenes, without necessarily going into all the
details.
So let's first have a look in the `.git/hg` directory, which typically
contains a subdirectory for each remote Mercurial repo alias, as well as a `.hg`
subdirectory. If the Mercurial repo is a local one, it will (again typically)
only contain a `marks-git` and a `marks-hg` file. If the repo is a remote one,
then the `clone` contains, well, a local clone of the remote. However, all
these clones share storage through the `.hg` directory mentioned previously (so
they do not add up separately). During a fetch/push, the local (proxy) repo is
used as an intermediate stage. If you would also prefer such an intermediate
stage for local repos, then setting the environment variable
`GIT_REMOTE_HG_TEST_REMOTE` will also use a proxy repo clone for a local repo.
As for the marks files, `marks-git` is created and used by `git-fast-export`
and `git-fast-import` and contains a mapping from mark to commit hash, where a
mark is essentially a plain number. `marks-hg` similarly contains a (JSON) based
mapping between such mark and hg revision hash. Together they provide for a
(consistent) view of the synchronization state of things.
When operating with shared-marks files, the `marks-git` and `marks-hg` files
are shared among all repos. As such, they are then found in the `.git/hg`
directory (rather than a repo subdirectory).
As there is really only one hg repository
(the shared storage "union bag" in `.git/hg/.hg`), only 1 set of marks files
should track the mapping between commit hash and revision hash.
Each individual remote then only adds some metadata (e.g regarding heads).
Upon a fetch, the helper uses the `marks-hg` file to decide what is already present
and what not. The required parts are then retrieved from Mercurial and turned
into a `git-fast-import` stream as expected by `import` capability of
https://www.kernel.org/pub/software/scm/git/docs/gitremote-helpers.html[gitremote-helpers(1)].
Upon a push, the helper has specified the `push` capability in the new approach, and
so git will provide a list of refspecs indicating what should go where.
If the refspecs indicates a remote delete, it is performed appropriately the Mercurial way.
If it is a regular push, then git-fast-export is invoked (using the existing `marks-git`)
and the stream is processed and turned into Mercurial commits (along with bookmarks, etc).
If the refspec specifies a `src:dest` rename, then the requested remote refname is tracked
accordingly. If a dry-run is requested, no remote is touched and no (marks) state of
the run is retained.

1089
git-hg-helper Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

45
setup.py Normal file
View File

@@ -0,0 +1,45 @@
# git-remote-hg setuptools script
import setuptools
# strip leading v
version = 'v1.0.5'[1:]
# check for released version
assert (len(version) > 0)
assert (version.find('-') < 0)
long_description = \
"""
'git-remote-hg' is a gitremote protocol helper for Mercurial.
It allows you to clone, fetch and push to and from Mercurial repositories as if
they were Git ones using a hg::some-url URL.
See the homepage for much more explanation.
"""
CLASSIFIERS = [
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"License :: OSI Approved",
"License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
]
setuptools.setup(name="git-remote-hg",
version=version,
author="Mark Nauwelaerts",
author_email="mnauw@users.sourceforge.net",
url="http://github.com/mnauw/git-remote-hg",
description="access hg repositories as git remotes",
long_description=long_description,
license="GPLv2",
keywords="git hg mercurial",
scripts=["git-remote-hg", "git-hg-helper"],
classifiers=CLASSIFIERS
)

3
t/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
test-results/
trash directory.*/
.prove

View File

@@ -1,9 +1,9 @@
RM ?= rm -f
T = $(wildcard ../test-*.sh)
TEST_DIRECTORY := $(CURDIR)
T = main.t main-push.t bidi.t helper.t
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

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Copyright (c) 2012 Felipe Contreras
#
@@ -8,19 +8,7 @@
test_description='Test bidirectionality of remote-hg'
. ./test-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
if ! python -c 'import mercurial'
then
skip_all='skipping remote-hg tests; mercurial not available'
test_done
fi
. "$(dirname "$0")"/test-lib.sh
# clone to a git repo
git_clone () {
@@ -45,26 +33,26 @@ hg_push () {
git checkout -q -b tmp &&
git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
git checkout -q @{-1} &&
git branch -q -D tmp 2>/dev/null || true
git branch -q -D tmp 2> /dev/null || true
)
}
hg_log () {
hg -R $1 log --graph --debug
hg -R $1 log --debug
}
setup () {
(
echo "[ui]"
echo "username = A U Thor <author@example.com>"
echo "[defaults]"
echo "backout = -d \"0 0\""
echo "commit = -d \"0 0\""
echo "debugrawcommit = -d \"0 0\""
echo "tag = -d \"0 0\""
echo "[extensions]"
echo "graphlog ="
) >>"$HOME"/.hgrc &&
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]"
graphlog =
EOF
git config --global remote-hg.hg-git-compat true
git config --global remote-hg.track-branches true
@@ -83,22 +71,22 @@ test_expect_success 'encoding' '
git init -q gitrepo &&
cd gitrepo &&
echo alpha >alpha &&
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 &&
echo beta > beta &&
git add beta &&
git commit -m "add beta" &&
echo gamma >gamma &&
echo gamma > gamma &&
git add gamma &&
git commit -m "add gämmâ" &&
: TODO git config i18n.commitencoding latin-1 &&
echo delta >delta &&
echo delta > delta &&
git add delta &&
git commit -m "add déltà"
) &&
@@ -107,8 +95,8 @@ test_expect_success 'encoding' '
git_clone hgrepo gitrepo2 &&
hg_clone gitrepo2 hgrepo2 &&
HGENCODING=utf-8 hg_log hgrepo >expected &&
HGENCODING=utf-8 hg_log hgrepo2 >actual &&
HGENCODING=utf-8 hg_log hgrepo > expected &&
HGENCODING=utf-8 hg_log hgrepo2 > actual &&
test_cmp expected actual
'
@@ -119,14 +107,14 @@ test_expect_success 'file removal' '
(
git init -q gitrepo &&
cd gitrepo &&
echo alpha >alpha &&
echo alpha > alpha &&
git add alpha &&
git commit -m "add alpha" &&
echo beta >beta &&
echo beta > beta &&
git add beta &&
git commit -m "add beta"
mkdir foo &&
echo blah >foo/bar &&
echo blah > foo/bar &&
git add foo &&
git commit -m "add foo" &&
git rm alpha &&
@@ -139,8 +127,8 @@ test_expect_success 'file removal' '
git_clone hgrepo gitrepo2 &&
hg_clone gitrepo2 hgrepo2 &&
hg_log hgrepo >expected &&
hg_log hgrepo2 >actual &&
hg_log hgrepo > expected &&
hg_log hgrepo2 > actual &&
test_cmp expected actual
'
@@ -152,12 +140,12 @@ test_expect_success 'git tags' '
git init -q gitrepo &&
cd gitrepo &&
git config receive.denyCurrentBranch ignore &&
echo alpha >alpha &&
echo alpha > alpha &&
git add alpha &&
git commit -m "add alpha" &&
git tag alpha &&
echo beta >beta &&
echo beta > beta &&
git add beta &&
git commit -m "add beta" &&
git tag -a -m "added tag beta" beta
@@ -167,8 +155,8 @@ test_expect_success 'git tags' '
git_clone hgrepo gitrepo2 &&
hg_clone gitrepo2 hgrepo2 &&
hg_log hgrepo >expected &&
hg_log hgrepo2 >actual &&
hg_log hgrepo > expected &&
hg_log hgrepo2 > actual &&
test_cmp expected actual
'
@@ -180,7 +168,7 @@ test_expect_success 'hg branch' '
git init -q gitrepo &&
cd gitrepo &&
echo alpha >alpha &&
echo alpha > alpha &&
git add alpha &&
git commit -q -m "add alpha" &&
git checkout -q -b not-master
@@ -203,8 +191,9 @@ test_expect_success 'hg branch' '
: Back to the common revision &&
(cd hgrepo && hg checkout default) &&
hg_log hgrepo >expected &&
hg_log hgrepo2 >actual &&
# fetch does not affect phase, but pushing now does
hg_log hgrepo | grep -v phase > expected &&
hg_log hgrepo2 | grep -v phase > actual &&
test_cmp expected actual
'
@@ -216,7 +205,7 @@ test_expect_success 'hg tags' '
git init -q gitrepo &&
cd gitrepo &&
echo alpha >alpha &&
echo alpha > alpha &&
git add alpha &&
git commit -m "add alpha" &&
git checkout -q -b not-master
@@ -231,10 +220,50 @@ test_expect_success 'hg tags' '
) &&
hg_push hgrepo gitrepo &&
hg_clone gitrepo hgrepo2 &&
# pushing a fetched tag is a problem ...
{ hg_clone gitrepo hgrepo2 || true ; } &&
hg_log hgrepo >expected &&
hg_log hgrepo2 >actual &&
# fetch does not affect phase, but pushing now does
hg_log hgrepo | grep -v phase > expected &&
hg_log hgrepo2 | grep -v phase > actual &&
test_cmp expected actual
'
test_expect_success 'test timezones' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
echo alpha > alpha &&
git add alpha &&
git commit -m "add alpha" --date="2007-01-01 00:00:00 +0000" &&
echo beta > beta &&
git add beta &&
git commit -m "add beta" --date="2007-01-01 00:00:00 +0100" &&
echo gamma > gamma &&
git add gamma &&
git commit -m "add gamma" --date="2007-01-01 00:00:00 -0100" &&
echo delta > delta &&
git add delta &&
git commit -m "add delta" --date="2007-01-01 00:00:00 +0130" &&
echo epsilon > epsilon &&
git add epsilon &&
git commit -m "add epsilon" --date="2007-01-01 00:00:00 -0130"
) &&
hg_clone gitrepo hgrepo &&
git_clone hgrepo gitrepo2 &&
hg_clone gitrepo2 hgrepo2 &&
hg_log hgrepo > expected &&
hg_log hgrepo2 > actual &&
test_cmp expected actual
'

View 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

View 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

View 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

View 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à

View 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

View 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

View 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

View 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
View 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

View 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
View 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

View 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

View 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
View 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

View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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

542
t/helper.t Executable file
View File

@@ -0,0 +1,542 @@
#!/bin/bash
#
# Copyright (c) 2016 Mark Nauwelaerts
#
# Base commands from hg-git tests:
# https://bitbucket.org/durin42/hg-git/src
#
test_description='Test git-hg-helper'
. "$(dirname "$0")"/test-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python with mercurial not available'
test_done
fi
setup () {
cat > "$HOME"/.hgrc <<-EOF &&
[ui]
username = H G Wells <wells@example.com>
[extensions]
mq =
strip =
[subrepos]
git:allowed = true
EOF
GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" &&
GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" &&
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
setup
setup_repos () {
(
hg init hgrepo &&
cd hgrepo &&
echo zero > content &&
hg add content &&
hg commit -m zero
) &&
git clone hg::hgrepo gitrepo
}
test_expect_success 'subcommand help' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repos &&
(
cd gitrepo &&
test_expect_code 2 git-hg-helper help 2> ../help
)
# remotes should be in help output
grep origin help
'
git config --global remote-hg.shared-marks false
test_expect_success 'subcommand repo - no local proxy' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repos &&
(
cd hgrepo &&
pwd >../expected
) &&
(
cd gitrepo &&
git-hg-helper repo origin > ../actual
) &&
test_cmp expected actual
'
git config --global --unset remote-hg.shared-marks
GIT_REMOTE_HG_TEST_REMOTE=1 &&
export GIT_REMOTE_HG_TEST_REMOTE
test_expect_success 'subcommand repo - with local proxy' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repos &&
(
cd gitrepo &&
export gitdir=`git rev-parse --git-dir`
# trick to normalize path
( cd $gitdir/hg/origin/clone && pwd ) >../expected &&
( cd `git-hg-helper repo origin` && pwd ) > ../actual
) &&
test_cmp expected actual
'
test_expect_success 'subcommands hg-rev and git-rev and mapfile' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repos &&
(
cd gitrepo &&
git rev-parse HEAD > rev-HEAD &&
test -s rev-HEAD &&
git-hg-helper hg-rev `cat rev-HEAD` > hg-HEAD &&
git-hg-helper git-rev `cat hg-HEAD` > git-HEAD &&
git-hg-helper mapfile --output mapfile origin &&
test_cmp rev-HEAD git-HEAD &&
grep "`cat rev-HEAD` `cat hg-HEAD`" mapfile
)
'
test_expect_success 'subcommand gc' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero > content &&
hg add content &&
hg commit -m zero
echo one > content &&
hg commit -m one &&
echo two > content &&
hg commit -m two &&
echo three > content &&
hg commit -m three
) &&
git clone hg::hgrepo gitrepo &&
(
cd hgrepo &&
hg strip -r 1 &&
echo four > content &&
hg commit -m four
) &&
(
cd gitrepo &&
git fetch origin &&
git reset --hard origin/master &&
git gc &&
git-hg-helper gc --check-hg origin > output &&
cat output &&
grep "hg marks" output &&
grep "git marks" output
)
'
test_expect_success 'subcommand [some-repo]' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repos &&
(
cd hgrepo &&
echo one > content &&
hg commit -m one
) &&
(
cd gitrepo &&
git fetch origin
) &&
hg log -R hgrepo > expected &&
# not inside gitrepo; test shared path handling
GIT_DIR=gitrepo/.git git-hg-helper origin log > actual
test_cmp expected actual
'
setup_repo () {
kind=$1 &&
repo=$2 &&
$kind init $repo &&
(
cd $repo &&
echo zero > content_$repo &&
$kind add content_$repo &&
$kind commit -m zero_$repo
)
}
check () {
echo $3 > expected &&
git --git-dir=$1/.git log --format='%s' -1 $2 > actual &&
test_cmp expected actual
}
check_branch () {
if test -n "$3"
then
echo $3 > expected &&
hg -R $1 log -r $2 --template '{desc}\n' > actual &&
test_cmp expected actual
else
hg -R $1 branches > out &&
! grep $2 out
fi
}
test_expect_success 'subcommand sub initial update (hg and git subrepos)' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repo hg hgrepo &&
(
cd hgrepo &&
setup_repo hg sub_hg_a &&
setup_repo hg sub_hg_b &&
setup_repo git sub_git &&
echo "sub_hg_a = sub_hg_a" > .hgsub &&
echo "sub_hg_b = sub_hg_b" >> .hgsub &&
echo "sub_git = [git]sub_git" >> .hgsub &&
hg add .hgsub &&
hg commit -m substate
)
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub update --force &&
test -f content_hgrepo &&
test -f sub_hg_a/content_sub_hg_a &&
test -f sub_hg_b/content_sub_hg_b &&
test -f sub_git/content_sub_git
) &&
check gitrepo HEAD substate &&
check gitrepo/sub_hg_a HEAD zero_sub_hg_a &&
check gitrepo/sub_hg_b HEAD zero_sub_hg_b &&
check gitrepo/sub_git HEAD zero_sub_git
'
setup_subrepos () {
setup_repo hg hgrepo &&
(
cd hgrepo &&
setup_repo hg sub_hg_a &&
(
cd sub_hg_a &&
setup_repo hg sub_hg_a_x &&
echo "sub_hg_a_x = sub_hg_a_x" > .hgsub &&
hg add .hgsub &&
hg commit -m substate_hg_a
) &&
setup_repo hg sub_hg_b &&
(
cd sub_hg_b &&
setup_repo git sub_git &&
echo "sub_git = [git]sub_git" > .hgsub &&
hg add .hgsub &&
hg commit -m substate_hg_b
) &&
echo "sub_hg_a = sub_hg_a" > .hgsub &&
echo "sub_hg_b = sub_hg_b" >> .hgsub &&
hg add .hgsub &&
hg commit -m substate
)
}
test_expect_success 'subcommand sub initial recursive update' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_subrepos &&
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub --recursive update --force &&
test -f content_hgrepo &&
test -f sub_hg_a/content_sub_hg_a &&
test -f sub_hg_a/sub_hg_a_x/content_sub_hg_a_x &&
test -f sub_hg_b/content_sub_hg_b &&
test -f sub_hg_b/sub_git/content_sub_git
) &&
check gitrepo HEAD substate &&
check gitrepo/sub_hg_a HEAD substate_hg_a &&
check gitrepo/sub_hg_b HEAD substate_hg_b &&
check gitrepo/sub_hg_a/sub_hg_a_x HEAD zero_sub_hg_a_x &&
check gitrepo/sub_hg_b/sub_git HEAD zero_sub_git
'
test_sub_update () {
export option=$1
setup_subrepos &&
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub --recursive update --force
) &&
(
cd hgrepo &&
(
cd sub_hg_a &&
(
cd sub_hg_a_x &&
echo one > content_sub_hg_a_x &&
hg commit -m one_sub_hg_a_x
) &&
hg commit -m substate_updated_hg_a
) &&
hg commit -m substate_updated
) &&
(
cd gitrepo &&
git fetch origin &&
git merge origin/master &&
git-hg-helper sub --recursive update --force $option &&
test -f content_hgrepo &&
test -f sub_hg_a/content_sub_hg_a &&
test -f sub_hg_a/sub_hg_a_x/content_sub_hg_a_x &&
test -f sub_hg_b/content_sub_hg_b &&
test -f sub_hg_b/sub_git/content_sub_git
) &&
check gitrepo HEAD substate_updated &&
check gitrepo/sub_hg_a HEAD substate_updated_hg_a &&
check gitrepo/sub_hg_b HEAD substate_hg_b &&
check gitrepo/sub_hg_a/sub_hg_a_x HEAD one_sub_hg_a_x &&
check gitrepo/sub_hg_b/sub_git HEAD zero_sub_git
}
test_expect_success 'subcommand sub subsequent recursive update' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
test_sub_update
'
test_expect_success 'subcommand sub subsequent recursive update -- rebase' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
test_sub_update --rebase
'
test_expect_success 'subcommand sub subsequent recursive update -- merge' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
test_sub_update --merge
'
check_foreach_vars () {
cat $1 | while read kind sha1 rev path remainder
do
ok=0
if test "$kind" = "hg" ; then
if test "$sha1" != "$rev" ; then
ok=1
fi
else
if test "$sha1" = "$rev" ; then
ok=1
fi
fi
test $ok -eq 1 || echo "invalid $kind $sha1 $rev $path"
test $ok -eq 1 || return 1
done &&
return 0
}
test_sub_foreach () {
setup_subrepos &&
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub --recursive update --force &&
git-hg-helper sub --recursive --quiet foreach 'echo $kind $sha1 $rev $path $toplevel' > output &&
cat output &&
echo 1 > expected_git &&
grep -c ^git output > actual_git &&
test_cmp expected_git actual_git &&
echo 3 > expected_hg &&
grep -c ^hg output > actual_hg &&
test_cmp expected_hg actual_hg &&
grep '\(hg\|git\) [0-9a-f]* [0-9a-f]* sub[^ ]* /.*' output > actual &&
test_cmp output actual &&
check_foreach_vars output
)
}
test_expect_success 'subcommand sub foreach' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
test_sub_foreach
'
test_expect_success 'subcommand sub sync' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repo hg hgrepo &&
(
cd hgrepo &&
setup_repo hg sub_hg &&
echo "sub_hg = sub_hg" > .hgsub &&
hg add .hgsub &&
hg commit -m substate
)
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub update --force &&
(
cd sub_hg &&
grep url .git/config > ../expected &&
git config remote.origin.url foobar &&
grep foobar .git/config
) &&
git-hg-helper sub sync &&
grep url sub_hg/.git/config > actual &&
test_cmp expected actual
)
'
test_expect_success 'subcommand sub addstate' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repo hg hgrepo &&
(
cd hgrepo &&
setup_repo hg sub_hg &&
setup_repo git sub_git &&
echo "sub_hg = sub_hg" > .hgsub &&
echo "sub_git = [git]sub_git" >> .hgsub &&
hg add .hgsub &&
hg commit -m substate
)
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub update --force &&
(
cd sub_hg &&
echo one > content_sub_hg &&
git add content_sub_hg &&
git commit -m one_sub_hg &&
# detached HEAD
git push origin HEAD:master &&
# also fetch to ensure notes are updated
git fetch origin
) &&
(
cd sub_git &&
echo one > content_sub_git &&
git add content_sub_git &&
git commit -m one_sub_git &&
# detached HEAD; push revision to other side ... anywhere
git push origin HEAD:refs/heads/new
)
) &&
(
cd gitrepo &&
git-hg-helper sub upstate &&
git diff &&
git status --porcelain | grep .hgsubstate &&
git add .hgsubstate &&
git commit -m update_sub &&
git push origin master
) &&
hg clone hgrepo hgclone &&
(
cd hgclone &&
hg update
) &&
check_branch hgclone default update_sub &&
check_branch hgclone/sub_hg default one_sub_hg &&
check hgclone/sub_git HEAD one_sub_git
'
test_expect_success 'subcommand sub status' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repo hg hgrepo &&
(
cd hgrepo &&
setup_repo hg sub_hg_a &&
setup_repo hg sub_hg_b &&
setup_repo git sub_git &&
echo "sub_hg_a = sub_hg_a" > .hgsub &&
echo "sub_hg_b = sub_hg_b" >> .hgsub &&
echo "sub_git = [git]sub_git" >> .hgsub &&
hg add .hgsub &&
hg commit -m substate
)
git clone hg::hgrepo gitrepo &&
(
cd gitrepo &&
git-hg-helper sub update --force sub_hg_a &&
git-hg-helper sub update --force sub_git &&
(
# advance and add a tag to the git repo
cd sub_git &&
echo one > content_sub_git &&
git add content_sub_git &&
git commit -m one_sub_git &&
git tag feature-a
) &&
git-hg-helper sub status --cached > output &&
cat output &&
grep "^ .*sub_hg_a (.*master.*)$" output &&
grep "^-.*sub_hg_b$" output &&
grep "^+.*sub_git (feature-a~1)$" output &&
git-hg-helper sub status sub_git > output &&
cat output &&
grep "^+.*sub_git (feature-a)$" output > actual &&
test_cmp output actual
)
'
test_done

446
t/hg-git.t Executable file
View 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

314
t/main-push.t Executable file
View File

@@ -0,0 +1,314 @@
#!/bin/bash
CAPABILITY_PUSH=t
. "$(dirname "$0")"/main.t
# .. and some push mode only specific tests
test_expect_success 'remote delete bookmark' '
test_when_finished "rm -rf hgrepo* gitrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero > content &&
hg add content &&
hg commit -m zero
hg bookmark feature-a
) &&
git clone "hg::hgrepo" gitrepo &&
check_bookmark hgrepo feature-a zero &&
(
cd gitrepo &&
git push --quiet origin :feature-a
) &&
check_bookmark hgrepo feature-a ''
'
test_expect_success 'source:dest bookmark' '
test_when_finished "rm -rf hgrepo gitrepo" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero > content &&
hg add content &&
hg commit -m zero
) &&
git clone "hg::hgrepo" gitrepo &&
(
cd gitrepo &&
echo one > content &&
git commit -a -m one &&
git push --quiet origin master:feature-b &&
git push --quiet origin master^:refs/heads/feature-a
) &&
check_bookmark hgrepo feature-a zero &&
check_bookmark hgrepo feature-b one &&
(
cd gitrepo &&
git push --quiet origin master:feature-a
) &&
check_bookmark hgrepo feature-a one
'
setup_check_hg_commits_repo () {
(
rm -rf hgrepo* &&
hg init hgrepo &&
cd hgrepo &&
echo zero > content &&
hg add content &&
hg commit -m zero
) &&
git clone "hg::hgrepo" gitrepo &&
hg clone hgrepo hgrepo.second &&
(
cd gitrepo &&
git remote add second hg::../hgrepo.second &&
git fetch second
) &&
(
cd hgrepo &&
echo one > content &&
hg commit -m one &&
echo two > content &&
hg commit -m two &&
echo three > content &&
hg commit -m three &&
hg move content content-move &&
hg commit -m moved &&
hg move content-move content &&
hg commit -m restored
)
}
# a shared bag would make all of the following pretty trivial
git config --global remote-hg.shared-marks false
git config --global remote-hg.check-hg-commits fail
test_expect_success 'check-hg-commits with fail mode' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_check_hg_commits_repo &&
(
cd gitrepo &&
git fetch origin &&
git reset --hard origin/master &&
! git push second master 2>../error
)
cat error &&
grep rejected error | grep hg
'
git config --global remote-hg.check-hg-commits push
# codepath for push is slightly different depending on shared proxy involved
# so tweak to test both
check_hg_commits_push () {
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_check_hg_commits_repo &&
(
cd gitrepo &&
git fetch origin &&
git reset --hard origin/master &&
git push second master 2> ../error
) &&
cat error &&
grep "hg changeset" error &&
hg log -R hgrepo > expected &&
hg log -R hgrepo.second | grep -v bookmark > actual &&
test_cmp expected actual
}
unset GIT_REMOTE_HG_TEST_REMOTE
test_expect_success 'check-hg-commits with push mode - no local proxy' '
check_hg_commits_push
'
GIT_REMOTE_HG_TEST_REMOTE=1 &&
export GIT_REMOTE_HG_TEST_REMOTE
test_expect_success 'check-hg-commits with push mode - with local proxy' '
check_hg_commits_push
'
setup_check_shared_marks_repo () {
(
rm -rf hgrepo* &&
hg init hgrepo &&
cd hgrepo &&
echo zero > content &&
hg add content &&
hg commit -m zero
) &&
git clone "hg::hgrepo" gitrepo &&
(
cd gitrepo &&
git remote add second hg::../hgrepo &&
git fetch second
)
}
check_marks () {
dir=$1
ls -al $dir &&
if test "$2" = "y"
then
test -f $dir/marks-git && test -f $dir/marks-hg
else
test ! -f $dir/marks-git && test ! -f $dir/marks-hg
fi
}
# cleanup setting
git config --global --unset remote-hg.shared-marks
test_expect_success 'shared-marks unset' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_check_shared_marks_repo &&
(
cd gitrepo &&
check_marks .git/hg y &&
check_marks .git/hg/origin n &&
check_marks .git/hg/second n
)
'
test_expect_success 'shared-marks set to unset' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
git config --global remote-hg.shared-marks true &&
setup_check_shared_marks_repo &&
(
cd gitrepo &&
check_marks .git/hg y &&
check_marks .git/hg/origin n &&
check_marks .git/hg/second n
) &&
git config --global remote-hg.shared-marks false &&
(
cd gitrepo &&
git fetch origin &&
check_marks .git/hg n &&
check_marks .git/hg/origin y &&
check_marks .git/hg/second y
)
'
test_expect_success 'shared-marks unset to set' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
git config --global remote-hg.shared-marks false &&
setup_check_shared_marks_repo &&
(
cd gitrepo &&
check_marks .git/hg n &&
check_marks .git/hg/origin y &&
check_marks .git/hg/second y
) &&
git config --global --unset remote-hg.shared-marks &&
(
cd gitrepo &&
git fetch origin &&
check_marks .git/hg n &&
check_marks .git/hg/origin y &&
check_marks .git/hg/second y
) &&
git config --global remote-hg.shared-marks true &&
(
cd gitrepo &&
git fetch origin &&
check_marks .git/hg y &&
check_marks .git/hg/origin n &&
check_marks .git/hg/second n
)
'
test_expect_success 'push with renamed executable preserves executable bit' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
hg init hgrepo &&
(
git init gitrepo &&
cd gitrepo &&
git remote add origin "hg::../hgrepo" &&
echo one > content &&
chmod a+x content &&
git add content &&
git commit -a -m one &&
git mv content content2 &&
git commit -a -m two &&
git push origin master
) &&
(
umask 0 &&
cd hgrepo &&
hg update &&
stat content2 >expected &&
grep -- -r.xr.xr.x expected
)
'
test_expect_success 'push with submodule' '
test_when_finished "rm -rf sub hgrepo gitrepo*" &&
hg init hgrepo &&
(
git init sub &&
cd sub &&
: >empty &&
git add empty &&
git commit -m init
) &&
(
git init gitrepo &&
cd gitrepo &&
git submodule add ../sub sub &&
git remote add origin "hg::../hgrepo" &&
git commit -a -m sub &&
git push origin master
) &&
(
cd hgrepo &&
hg update &&
expected="[git-remote-hg: skipped import of submodule at $(git -C ../sub rev-parse HEAD)]"
test "$expected" = "$(cat sub)"
)
'
# cleanup setting
git config --global --unset remote-hg.shared-marks
test_done

1397
t/main.t Executable file

File diff suppressed because it is too large Load Diff

760
t/sharness.sh Normal file
View File

@@ -0,0 +1,760 @@
# 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
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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.2.1"
export SHARNESS_VERSION
: "${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.
export SHARNESS_TEST_DIRECTORY
: "${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
[ -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:=/bin/sh}"
export SHELL_PATH
# if --tee was passed, write the output not only to the terminal, but
# additionally to the file test-results/$BASENAME.out, too.
case "$SHARNESS_TEST_TEE_STARTED, $* " in
done,*)
# do not redirect again
;;
*' --tee '*|*' --verbose-log '*)
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.
SHARNESS_TEST_TEE_OUTPUT_FILE="$BASE.out"
export SHARNESS_TEST_TEE_OUTPUT_FILE
# Truncate before calling "tee -a" to get rid of the results
# from any previous runs.
: >"$SHARNESS_TEST_TEE_OUTPUT_FILE"
(SHARNESS_TEST_TEE_STARTED="done" ${SHELL_PATH} "$0" "$@" 2>&1;
echo $? >"$BASE.exit") | tee -a "$SHARNESS_TEST_TEE_OUTPUT_FILE"
test "$(cat "$BASE.exit")" = 0
exit
;;
esac
# For repeatability, reset the environment to a known state.
# TERM is sanitized below, after saving color control sequences.
LANG=C
LC_ALL=C
PAGER="cat"
TZ=UTC
EDITOR=:
export LANG LC_ALL PAGER TZ EDITOR
unset VISUAL CDPATH GREP_OPTIONS
[ "x$TERM" != "xdumb" ] && (
[ -t 1 ] &&
tput bold >/dev/null 2>&1 &&
tput setaf 1 >/dev/null 2>&1 &&
tput sgr0 >/dev/null 2>&1
) &&
color=t
while test "$#" -ne 0; do
case "$1" in
-d|--d|--de|--deb|--debu|--debug)
debug=t; shift ;;
-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
immediate=t; shift ;;
-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
TEST_LONG=t; export TEST_LONG; shift ;;
--in|--int|--inte|--inter|--intera|--interac|--interact|--interacti|--interactiv|--interactive|--interactive-|--interactive-t|--interactive-te|--interactive-tes|--interactive-test|--interactive-tests):
TEST_INTERACTIVE=t; export TEST_INTERACTIVE; verbose=t; shift ;;
-h|--h|--he|--hel|--help)
help=t; shift ;;
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
verbose=t; shift ;;
-q|--q|--qu|--qui|--quie|--quiet)
# Ignore --quiet under a TAP::Harness. Saying how many tests
# passed without the ok/not ok details is always an error.
test -z "$HARNESS_ACTIVE" && quiet=t; shift ;;
--chain-lint)
chain_lint=t; shift ;;
--no-chain-lint)
chain_lint=; shift ;;
--no-color)
color=; shift ;;
--tee)
shift ;; # was handled already
--root=*)
root=$(expr "z$1" : 'z[^=]*=\(.*\)')
shift ;;
-x)
trace=t
shift ;;
--verbose-log)
verbose_log=t
shift ;;
*)
echo "error: unknown test option '$1'" >&2; exit 1 ;;
esac
done
if test -n "$color"; then
# Save the color control sequences now rather than run tput
# each time say_color() is called. This is done for two
# reasons:
# * TERM will be changed to dumb
# * HOME will be changed to a temporary directory and tput
# might need to read ~/.terminfo from the original HOME
# directory to get the control sequences
# Note: This approach assumes the control sequences don't end
# in a newline for any terminal of interest (command
# substitutions strip trailing newlines). Given that most
# (all?) terminals in common use are related to ECMA-48, this
# shouldn't be a problem.
say_color_error=$(tput bold; tput setaf 1) # bold red
say_color_skip=$(tput setaf 4) # blue
say_color_warn=$(tput setaf 3) # brown/yellow
say_color_pass=$(tput setaf 2) # green
say_color_info=$(tput setaf 6) # cyan
say_color_reset=$(tput sgr0)
say_color_raw="" # no formatting for normal text
say_color() {
test -z "$1" && test -n "$quiet" && return
case "$1" in
error) say_color_color=$say_color_error ;;
skip) say_color_color=$say_color_skip ;;
warn) say_color_color=$say_color_warn ;;
pass) say_color_color=$say_color_pass ;;
info) say_color_color=$say_color_info ;;
*) say_color_color=$say_color_raw ;;
esac
shift
printf '%s%s%s\n' "$say_color_color" "$*" "$say_color_reset"
}
else
say_color() {
test -z "$1" && test -n "$quiet" && return
shift
printf '%s\n' "$*"
}
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
error() {
say_color error "error: $*"
EXIT_OK=t
exit 1
}
say() {
say_color info "$*"
}
test -n "${test_description:-}" || error "Test script did not set test_description."
if test "$help" = "t"; then
echo "$test_description"
exit 0
fi
exec 5>&1
exec 6<&0
if test "$verbose_log" = "t"
then
exec 3>>"$SHARNESS_TEST_TEE_OUTPUT_FILE" 4>&3
elif test "$verbose" = "t"
then
exec 4>&2 3>&1
else
exec 4>/dev/null 3>/dev/null
fi
# 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=$?
if test -n "$EXIT_OK"; then
exit $code
else
echo >&5 "FATAL: Unexpected exit with code $code"
exit 1
fi
}
EXIT_OK=
trap 'die' EXIT
test_prereq=
missing_prereq=
test_failure=0
test_fixed=0
test_broken=0
test_success=0
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 $SHARNESS_TEST_NB - $*"
}
test_failure_() {
test_failure=$((test_failure + 1))
say_color error "not ok $SHARNESS_TEST_NB - $1"
shift
echo "$@" | sed -e 's/^/# /'
test "$immediate" = "" || { EXIT_OK=t; exit 1; }
}
test_known_broken_ok_() {
test_fixed=$((test_fixed + 1))
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 $SHARNESS_TEST_NB - $* # TODO known breakage"
}
want_trace () {
test "$trace" = t && {
test "$verbose" = t || test "$verbose_log" = t
}
}
# 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_() {
case ",$test_prereq," in
*,INTERACTIVE,*)
eval "$*"
;;
*)
test_eval_x_ "$@"
;;
esac
}
test_run_() {
test_cleanup=:
expecting_failure=$2
test_eval_ "$1"
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" && test "$test_cleanup" != ":"
then
test_eval_ "$test_cleanup"
fi
if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
echo ""
fi
return "$eval_ret"
}
test_skip_() {
SHARNESS_TEST_NB=$((SHARNESS_TEST_NB + 1))
to_skip=
for skp in $SKIP_TESTS; do
# shellcheck disable=SC2254
case $this_test.$SHARNESS_TEST_NB in
$skp)
to_skip=t
break
esac
done
if test -z "$to_skip" && test -n "$test_prereq" && ! test_have_prereq "$test_prereq"; then
to_skip=t
fi
case "$to_skip" in
t)
of_prereq=
if test "$missing_prereq" != "$test_prereq"; then
of_prereq=" of $test_prereq"
fi
say_color skip >&3 "skipping test: $*"
say_color skip "ok $SHARNESS_TEST_NB # skip $1 (missing $missing_prereq${of_prereq})"
: true
;;
*)
false
;;
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
# tests is incremented. When it failed, a "not ok" message is printed and the
# number of failed tests is incremented.
#
# With --immediate, exit test immediately upon the first failed test.
#
# Usually takes two arguments:
# $1 - Test description
# $2 - Commands to be executed.
#
# With three arguments, the first will be taken to be a prerequisite:
# $1 - Comma-separated list of test prerequisites. The test will be skipped if
# not all of the given prerequisites are set. To negate a prerequisite,
# put a "!" in front of it.
# $2 - Test description
# $3 - Commands to be executed.
#
# Examples
#
# test_expect_success \
# 'git-write-tree should be able to write an empty tree.' \
# 'tree=$(git-write-tree)'
#
# # Test depending on one prerequisite.
# test_expect_success TTY 'git --paginate rev-list uses a pager' \
# ' ... '
#
# # Multiple prerequisites are separated by a comma.
# test_expect_success PERL,PYTHON 'yo dawg' \
# ' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" '
#
# Returns nothing.
test_expect_success() {
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_success"
export test_prereq
if ! test_skip_ "$@"; then
say >&3 "expecting success: $2"
if test_run_ "$2"; then
test_ok_ "$1"
else
test_failure_ "$@"
fi
fi
echo >&3 ""
}
# Public: Run test commands and expect them to fail. Used to demonstrate a known
# breakage.
#
# This is NOT the opposite of test_expect_success, but rather used to mark a
# test that demonstrates a known breakage.
#
# When the test passed, an "ok" message is printed and the number of fixed tests
# is incremented. When it failed, a "not ok" message is printed and the number
# of tests still broken is incremented.
#
# Failures from these tests won't cause --immediate to stop.
#
# Usually takes two arguments:
# $1 - Test description
# $2 - Commands to be executed.
#
# With three arguments, the first will be taken to be a prerequisite:
# $1 - Comma-separated list of test prerequisites. The test will be skipped if
# not all of the given prerequisites are set. To negate a prerequisite,
# put a "!" in front of it.
# $2 - Test description
# $3 - Commands to be executed.
#
# Returns nothing.
test_expect_failure() {
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_failure"
export test_prereq
if ! test_skip_ "$@"; then
say >&3 "checking known breakage: $2"
if test_run_ "$2" expecting_failure; then
test_known_broken_ok_ "$1"
else
test_known_broken_failure_ "$1"
fi
fi
echo >&3 ""
}
# Public: Run test commands and expect anything from them. Used when a
# test is not stable or not finished for some reason.
#
# When the test passed, an "ok" message is printed, but the number of
# fixed tests is not incremented.
#
# When it failed, a "not ok ... # TODO known breakage" message is
# printed, and the number of tests still broken is incremented.
#
# Failures from these tests won't cause --immediate to stop.
#
# Usually takes two arguments:
# $1 - Test description
# $2 - Commands to be executed.
#
# With three arguments, the first will be taken to be a prerequisite:
# $1 - Comma-separated list of test prerequisites. The test will be skipped if
# not all of the given prerequisites are set. To negate a prerequisite,
# put a "!" in front of it.
# $2 - Test description
# $3 - Commands to be executed.
#
# Returns nothing.
test_expect_unstable() {
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_unstable"
export test_prereq
if ! test_skip_ "$@"; then
say >&3 "checking unstable test: $2"
if test_run_ "$2" unstable; then
test_ok_ "$1"
else
test_known_broken_failure_ "$1"
fi
fi
echo >&3 ""
}
# Public: Summarize test results and exit with an appropriate error code.
#
# Must be called at the end of each test script.
#
# Can also be used to stop tests early and skip all remaining tests. For this,
# set skip_all to a string explaining why the tests were skipped before calling
# test_done.
#
# Examples
#
# # Each test script must call test_done at the end.
# test_done
#
# # 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 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_OUTDIR/test-results"
mkdir -p "$test_results_dir"
test_results_path="$test_results_dir/$this_test.$$.counts"
cat >>"$test_results_path" <<-EOF
total $SHARNESS_TEST_NB
success $test_success
fixed $test_fixed
broken $test_broken
failed $test_failure
EOF
fi
if test "$test_fixed" != 0; then
say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
fi
if test "$test_broken" != 0; then
say_color warn "# still have $test_broken known breakage(s)"
fi
if test "$test_broken" != 0 || test "$test_fixed" != 0; then
test_remaining=$((SHARNESS_TEST_NB - test_broken - test_fixed))
msg="remaining $test_remaining test(s)"
else
test_remaining=$SHARNESS_TEST_NB
msg="$SHARNESS_TEST_NB test(s)"
fi
case "$test_failure" in
0)
# Maybe print SKIP message
check_skip_all_
if test "$test_remaining" -gt 0; then
say_color pass "# passed all $msg"
fi
say "1..$SHARNESS_TEST_NB$skip_all"
test_eval_ "$final_cleanup"
remove_trash_
exit 0 ;;
*)
say_color error "# failed $test_failure among $msg"
say "1..$SHARNESS_TEST_NB"
exit 1 ;;
esac
}
: "${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.
export SHARNESS_BUILD_DIRECTORY
PATH="$SHARNESS_BUILD_DIRECTORY:$PATH"
export PATH
# Public: Path to test script currently executed.
SHARNESS_TEST_FILE="$0"
export SHARNESS_TEST_FILE
# Prepare test area.
SHARNESS_TRASH_DIRECTORY="trash directory.$(basename "$SHARNESS_TEST_FILE" ".$SHARNESS_TEST_EXTENSION")"
test -n "$root" && SHARNESS_TRASH_DIRECTORY="$root/$SHARNESS_TRASH_DIRECTORY"
case "$SHARNESS_TRASH_DIRECTORY" in
/*) ;; # absolute path is good
*) SHARNESS_TRASH_DIRECTORY="$SHARNESS_TEST_OUTDIR/$SHARNESS_TRASH_DIRECTORY" ;;
esac
test "$debug" = "t" || remove_trash="$SHARNESS_TRASH_DIRECTORY"
rm -rf "$SHARNESS_TRASH_DIRECTORY" || {
EXIT_OK=t
echo >&5 "FATAL: Cannot prepare test area"
exit 1
}
#
# Load any extensions in $testdir/sharness.d/*.sh
#
if test -d "${SHARNESS_TEST_DIRECTORY}/sharness.d"
then
for file in "${SHARNESS_TEST_DIRECTORY}"/sharness.d/*.sh
do
# Ensure glob was not an empty match:
test -e "${file}" || break
if test -n "$debug"
then
echo >&5 "sharness: loading extensions from ${file}"
fi
# shellcheck disable=SC1090
. "${file}"
if test $? != 0
then
echo >&5 "sharness: Error loading ${file}. Aborting."
exit 1
fi
done
fi
# Public: Empty trash directory, the test area, provided for each test. The HOME
# variable is set to that directory too.
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"}
for skp in $SKIP_TESTS; do
# shellcheck disable=SC2254
case "$this_test" in
$skp)
say_color info >&3 "skipping test $this_test altogether"
skip_all="skip all tests in $this_test"
test_done
esac
done
test -n "$TEST_LONG" && test_set_prereq EXPENSIVE
test -n "$TEST_INTERACTIVE" && test_set_prereq INTERACTIVE
# Make sure this script ends with code 0
:
# vi: set ts=4 sw=4 noet :

136
t/test-lib.sh Normal file
View File

@@ -0,0 +1,136 @@
#!/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"
do
f="$d/sharness.sh"
if [ -f "$f" ] ; then
SHARNESS="$f"
fi
done
fi
if [ -z "$SHARNESS" ] || [ ! -f "$SHARNESS" ] ; then
echo "sharness.sh not found" >&2
exit 1
fi
# Prevent sharness from adding the source directory to PATH
# since the scripts use unversioned python for their shebang
# but tests should run under the python with mercurial support
# so create an empty directory and strip it from PATH afterwards
SHARNESS_BUILD_DIRECTORY="$(mktemp -d)"
. "$SHARNESS"
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
elif python3 -c 'import mercurial' 2> /dev/null ; then
PYTHON=python3
elif python2 -c 'import mercurial' 2> /dev/null ; then
PYTHON=python2
elif python -c 'import mercurial' 2> /dev/null ; then
PYTHON=python
fi
if [ -n "$PYTHON" ] ; then
test_set_prereq PYTHON
# Change shebang on a copy of scripts to chosen Python version
TEST_BIN="$SHARNESS_TRASH_DIRECTORY/bin"
mkdir -p "$TEST_BIN"
for s in git-remote-hg git-hg-helper ; do
printf "%s\n" "#!/usr/bin/env $PYTHON" > "$TEST_BIN/$s"
tail -n +2 "$SHARNESS_TEST_DIRECTORY/../$s" >> "$TEST_BIN/$s"
chmod u+x "$TEST_BIN/$s"
done
export PATH="$TEST_BIN${PATH:+:$PATH}"
unset TEST_BIN
fi
else
# The build/install process ensures Python is available
test_set_prereq PYTHON
fi

View File

@@ -1,541 +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-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
if ! python -c 'import mercurial'
then
skip_all='skipping remote-hg tests; mercurial not available'
test_done
fi
if ! python -c 'import hggit'
then
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 () {
(
echo "[ui]"
echo "username = A U Thor <author@example.com>"
echo "[defaults]"
echo "backout = -d \"0 0\""
echo "commit = -d \"0 0\""
echo "debugrawcommit = -d \"0 0\""
echo "tag = -d \"0 0\""
echo "[extensions]"
echo "hgext.bookmarks ="
echo "hggit ="
echo "graphlog ="
) >>"$HOME"/.hgrc &&
git config --global receive.denycurrentbranch warn
git config --global remote-hg.hg-git-compat true
git config --global remote-hg.track-branches 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 '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

View File

@@ -1,775 +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'
test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=${0%/*}/../../t
. "$TEST_DIRECTORY"/test-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
if ! python -c 'import mercurial'
then
skip_all='skipping remote-hg tests; mercurial not available'
test_done
fi
check () {
echo $3 >expected &&
git --git-dir=$1/.git log --format='%s' -1 $2 >actual
test_cmp expected actual
}
check_branch () {
if test -n "$3"
then
echo $3 >expected &&
hg -R $1 log -r $2 --template '{desc}\n' >actual &&
test_cmp expected actual
else
hg -R $1 branches >out &&
! grep $2 out
fi
}
check_bookmark () {
if test -n "$3"
then
echo $3 >expected &&
hg -R $1 log -r "bookmark('$2')" --template '{desc}\n' >actual &&
test_cmp expected actual
else
hg -R $1 bookmarks >out &&
! grep $2 out
fi
}
check_push () {
expected_ret=$1 ret=0 ref_ret=0
shift
git push origin "$@" 2>error
ret=$?
cat error
while IFS=':' read branch kind
do
case "$kind" in
'new')
grep "^ \* \[new branch\] *${branch} -> ${branch}$" error || ref_ret=1
;;
'non-fast-forward')
grep "^ ! \[rejected\] *${branch} -> ${branch} (non-fast-forward)$" error || ref_ret=1
;;
'fetch-first')
grep "^ ! \[rejected\] *${branch} -> ${branch} (fetch first)$" error || ref_ret=1
;;
'forced-update')
grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *${branch} -> ${branch} (forced update)$" error || ref_ret=1
;;
'')
grep "^ [a-f0-9]*\.\.[a-f0-9]* *${branch} -> ${branch}$" error || ref_ret=1
;;
esac
test $ref_ret -ne 0 && echo "match for '$branch' failed" && break
done
if test $expected_ret -ne $ret || test $ref_ret -ne 0
then
return 1
fi
return 0
}
setup () {
(
echo "[ui]"
echo "username = H G Wells <wells@example.com>"
echo "[extensions]"
echo "mq ="
) >>"$HOME"/.hgrc &&
GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" &&
GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" &&
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
setup
test_expect_success 'cloning' '
test_when_finished "rm -rf gitrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero >content &&
hg add content &&
hg commit -m zero
) &&
git clone "hg::hgrepo" gitrepo &&
check gitrepo HEAD zero
'
test_expect_success 'cloning with branches' '
test_when_finished "rm -rf gitrepo*" &&
(
cd hgrepo &&
hg branch next &&
echo next >content &&
hg commit -m next
) &&
git clone "hg::hgrepo" gitrepo &&
check gitrepo origin/branches/next next
'
test_expect_success 'cloning with bookmarks' '
test_when_finished "rm -rf gitrepo*" &&
(
cd hgrepo &&
hg checkout default &&
hg bookmark feature-a &&
echo feature-a >content &&
hg commit -m feature-a
) &&
git clone "hg::hgrepo" gitrepo &&
check gitrepo origin/feature-a feature-a
'
test_expect_success 'update bookmark' '
test_when_finished "rm -rf gitrepo*" &&
(
cd hgrepo &&
hg bookmark devel
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git checkout --quiet devel &&
echo devel >content &&
git commit -a -m devel &&
git push --quiet
) &&
check_bookmark hgrepo devel devel
'
test_expect_success 'new bookmark' '
test_when_finished "rm -rf gitrepo*" &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git checkout --quiet -b feature-b &&
echo feature-b >content &&
git commit -a -m feature-b &&
git push --quiet origin feature-b
) &&
check_bookmark hgrepo feature-b feature-b
'
# cleanup previous stuff
rm -rf hgrepo
author_test () {
echo $1 >>content &&
hg commit -u "$2" -m "add $1" &&
echo "$3" >>../expected
}
test_expect_success 'authors' '
test_when_finished "rm -rf hgrepo gitrepo" &&
(
hg init hgrepo &&
cd hgrepo &&
touch content &&
hg add content &&
>../expected &&
author_test alpha "" "H G Wells <wells@example.com>" &&
author_test beta "beta" "beta <unknown>" &&
author_test gamma "gamma <test@example.com> (comment)" "gamma <test@example.com>" &&
author_test delta "<delta@example.com>" "Unknown <delta@example.com>" &&
author_test epsilon "epsilon<test@example.com>" "epsilon <test@example.com>" &&
author_test zeta "zeta <test@example.com" "zeta <test@example.com>" &&
author_test eta " eta " "eta <unknown>" &&
author_test theta "theta < test@example.com >" "theta <test@example.com>" &&
author_test iota "iota >test@example.com>" "iota <test@example.com>" &&
author_test kappa "kappa < test <at> example <dot> com>" "kappa <unknown>" &&
author_test lambda "lambda@example.com" "Unknown <lambda@example.com>" &&
author_test mu "mu.mu@example.com" "Unknown <mu.mu@example.com>"
) &&
git clone "hg::hgrepo" gitrepo &&
git --git-dir=gitrepo/.git log --reverse --format="%an <%ae>" >actual &&
test_cmp expected actual
'
test_expect_success 'strip' '
test_when_finished "rm -rf hgrepo gitrepo" &&
(
hg init hgrepo &&
cd hgrepo &&
echo one >>content &&
hg add content &&
hg commit -m one &&
echo two >>content &&
hg commit -m two
) &&
git clone "hg::hgrepo" gitrepo &&
(
cd hgrepo &&
hg strip 1 &&
echo three >>content &&
hg commit -m three &&
echo four >>content &&
hg commit -m four
) &&
(
cd gitrepo &&
git fetch &&
git log --format="%s" origin/master >../actual
) &&
hg -R hgrepo log --template "{desc}\n" >expected &&
test_cmp actual expected
'
test_expect_success 'remote push with master bookmark' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero >content &&
hg add content &&
hg commit -m zero &&
hg bookmark master &&
echo one >content &&
hg commit -m one
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
echo two >content &&
git commit -a -m two &&
git push
) &&
check_branch hgrepo default two
'
cat >expected <<\EOF
changeset: 0:6e2126489d3d
tag: tip
user: A U Thor <author@example.com>
date: Mon Jan 01 00:00:00 2007 +0230
summary: one
EOF
test_expect_success 'remote push from master branch' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
hg init hgrepo &&
(
git init gitrepo &&
cd gitrepo &&
git remote add origin "hg::../hgrepo" &&
echo one >content &&
git add content &&
git commit -a -m one &&
git push origin master
) &&
hg -R hgrepo log >actual &&
cat actual &&
test_cmp expected actual &&
check_branch hgrepo default one
'
GIT_REMOTE_HG_TEST_REMOTE=1
export GIT_REMOTE_HG_TEST_REMOTE
test_expect_success 'remote cloning' '
test_when_finished "rm -rf gitrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero >content &&
hg add content &&
hg commit -m zero
) &&
git clone "hg::hgrepo" gitrepo &&
check gitrepo HEAD zero
'
test_expect_success 'moving remote clone' '
test_when_finished "rm -rf gitrepo*" &&
(
git clone "hg::hgrepo" gitrepo &&
mv gitrepo gitrepo2 &&
cd gitrepo2 &&
git fetch
)
'
test_expect_success 'remote update bookmark' '
test_when_finished "rm -rf gitrepo*" &&
(
cd hgrepo &&
hg bookmark devel
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git checkout --quiet devel &&
echo devel >content &&
git commit -a -m devel &&
git push --quiet
) &&
check_bookmark hgrepo devel devel
'
test_expect_success 'remote new bookmark' '
test_when_finished "rm -rf gitrepo*" &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git checkout --quiet -b feature-b &&
echo feature-b >content &&
git commit -a -m feature-b &&
git push --quiet origin feature-b
) &&
check_bookmark hgrepo feature-b feature-b
'
test_expect_success 'remote push diverged' '
test_when_finished "rm -rf gitrepo*" &&
git clone "hg::hgrepo" gitrepo &&
(
cd hgrepo &&
hg checkout default &&
echo bump >content &&
hg commit -m bump
) &&
(
cd gitrepo &&
echo diverge >content &&
git commit -a -m diverged &&
check_push 1 <<-\EOF
master:non-fast-forward
EOF
) &&
check_branch hgrepo default bump
'
test_expect_success 'remote update bookmark diverge' '
test_when_finished "rm -rf gitrepo*" &&
(
cd hgrepo &&
hg checkout tip^ &&
hg bookmark diverge
) &&
git clone "hg::hgrepo" gitrepo &&
(
cd hgrepo &&
echo "bump bookmark" >content &&
hg commit -m "bump bookmark"
) &&
(
cd gitrepo &&
git checkout --quiet diverge &&
echo diverge >content &&
git commit -a -m diverge &&
check_push 1 <<-\EOF
diverge:fetch-first
EOF
) &&
check_bookmark hgrepo diverge "bump bookmark"
'
test_expect_success 'remote new bookmark multiple branch head' '
test_when_finished "rm -rf gitrepo*" &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git checkout --quiet -b feature-c HEAD^ &&
echo feature-c >content &&
git commit -a -m feature-c &&
git push --quiet origin feature-c
) &&
check_bookmark hgrepo feature-c feature-c
'
# cleanup previous stuff
rm -rf hgrepo
test_expect_success 'fetch special filenames' '
test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
LC_ALL=en_US.UTF-8
export LC_ALL
(
hg init hgrepo &&
cd hgrepo &&
echo test >> "æ rø" &&
hg add "æ rø" &&
echo test >> "ø~?" &&
hg add "ø~?" &&
hg commit -m add-utf-8 &&
echo test >> "æ rø" &&
hg commit -m test-utf-8 &&
hg rm "ø~?" &&
hg mv "æ rø" "ø~?" &&
hg commit -m hg-mv-utf-8
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git -c core.quotepath=false ls-files > ../actual
) &&
echo "ø~?" > expected &&
test_cmp expected actual
'
test_expect_success 'push special filenames' '
test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
mkdir -p tmp && cd tmp &&
LC_ALL=en_US.UTF-8
export LC_ALL
(
hg init hgrepo &&
cd hgrepo &&
echo one >> content &&
hg add content &&
hg commit -m one
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
echo test >> "æ rø" &&
git add "æ rø" &&
git commit -m utf-8 &&
git push
) &&
(cd hgrepo &&
hg update &&
hg manifest > ../actual
) &&
printf "content\næ rø\n" > expected &&
test_cmp expected actual
'
setup_big_push () {
(
hg init hgrepo &&
cd hgrepo &&
echo zero >content &&
hg add content &&
hg commit -m zero &&
hg bookmark bad_bmark1 &&
echo one >content &&
hg commit -m one &&
hg bookmark bad_bmark2 &&
hg bookmark good_bmark &&
hg bookmark -i good_bmark &&
hg -q branch good_branch &&
echo "good branch" >content &&
hg commit -m "good branch" &&
hg -q branch bad_branch &&
echo "bad branch" >content &&
hg commit -m "bad branch"
) &&
git clone "hg::hgrepo" gitrepo &&
(
cd gitrepo &&
echo two >content &&
git commit -q -a -m two &&
git checkout -q good_bmark &&
echo three >content &&
git commit -q -a -m three &&
git checkout -q bad_bmark1 &&
git reset --hard HEAD^ &&
echo four >content &&
git commit -q -a -m four &&
git checkout -q bad_bmark2 &&
git reset --hard HEAD^ &&
echo five >content &&
git commit -q -a -m five &&
git checkout -q -b new_bmark master &&
echo six >content &&
git commit -q -a -m six &&
git checkout -q branches/good_branch &&
echo seven >content &&
git commit -q -a -m seven &&
echo eight >content &&
git commit -q -a -m eight &&
git checkout -q branches/bad_branch &&
git reset --hard HEAD^ &&
echo nine >content &&
git commit -q -a -m nine &&
git checkout -q -b branches/new_branch master &&
echo ten >content &&
git commit -q -a -m ten
)
}
test_expect_success 'remote big push' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_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
) &&
check_branch hgrepo default one &&
check_branch hgrepo good_branch "good branch" &&
check_branch hgrepo bad_branch "bad branch" &&
check_branch hgrepo new_branch '' &&
check_bookmark hgrepo good_bmark one &&
check_bookmark hgrepo bad_bmark1 one &&
check_bookmark hgrepo bad_bmark2 one &&
check_bookmark hgrepo new_bmark ''
'
test_expect_success 'remote big push fetch first' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero >content &&
hg add content &&
hg commit -m zero &&
hg bookmark bad_bmark &&
hg bookmark good_bmark &&
hg bookmark -i good_bmark &&
hg -q branch good_branch &&
echo "good branch" >content &&
hg commit -m "good branch" &&
hg -q branch bad_branch &&
echo "bad branch" >content &&
hg commit -m "bad branch"
) &&
git clone "hg::hgrepo" gitrepo &&
(
cd hgrepo &&
hg bookmark -f bad_bmark &&
echo update_bmark >content &&
hg commit -m "update bmark"
) &&
(
cd gitrepo &&
echo two >content &&
git commit -q -a -m two &&
git checkout -q good_bmark &&
echo three >content &&
git commit -q -a -m three &&
git checkout -q bad_bmark &&
echo four >content &&
git commit -q -a -m four &&
git checkout -q branches/bad_branch &&
echo five >content &&
git commit -q -a -m five &&
check_push 1 --all <<-\EOF &&
master
good_bmark
bad_bmark:fetch-first
branches/bad_branch:festch-first
EOF
git fetch &&
check_push 1 --all <<-\EOF
master
good_bmark
bad_bmark:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
)
'
test_expect_failure 'remote big push force' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_big_push
(
cd gitrepo &&
check_push 0 --force --all <<-\EOF
master
good_bmark
branches/good_branch
new_bmark:new
branches/new_branch:new
bad_bmark1:forced-update
bad_bmark2:forced-update
branches/bad_branch:forced-update
EOF
) &&
check_branch hgrepo default six &&
check_branch hgrepo good_branch eight &&
check_branch hgrepo bad_branch nine &&
check_branch hgrepo new_branch ten &&
check_bookmark hgrepo good_bmark three &&
check_bookmark hgrepo bad_bmark1 four &&
check_bookmark hgrepo bad_bmark2 five &&
check_bookmark hgrepo new_bmark six
'
test_expect_failure 'remote big push dry-run' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_big_push
(
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
check_push 0 --dry-run master good_bmark new_bmark branches/good_branch branches/new_branch <<-\EOF
master
good_bmark
branches/good_branch
new_bmark:new
branches/new_branch:new
EOF
) &&
check_branch hgrepo default one &&
check_branch hgrepo good_branch "good branch" &&
check_branch hgrepo bad_branch "bad branch" &&
check_branch hgrepo new_branch '' &&
check_bookmark hgrepo good_bmark one &&
check_bookmark hgrepo bad_bmark1 one &&
check_bookmark hgrepo bad_bmark2 one &&
check_bookmark hgrepo new_bmark ''
'
test_expect_success 'remote double failed push' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
(
hg init hgrepo &&
cd hgrepo &&
echo zero >content &&
hg add content &&
hg commit -m zero &&
echo one >content &&
hg commit -m one
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git reset --hard HEAD^ &&
echo two >content &&
git commit -a -m two &&
test_expect_code 1 git push &&
test_expect_code 1 git push
)
'
test_done

View File

@@ -1,711 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2011-2012 Mathias Lafeldt
# Copyright (c) 2005-2012 Git project
# Copyright (c) 2005-2012 Junio C Hamano
#
# 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
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/ .
# Public: Current version of Sharness.
SHARNESS_VERSION="0.3.0"
export SHARNESS_VERSION
# Public: The file extension for tests. By default, it is set to "t".
: ${SHARNESS_TEST_EXTENSION:=t}
export SHARNESS_TEST_EXTENSION
# Keep the original TERM for say_color
ORIGINAL_TERM=$TERM
# For repeatability, reset the environment to a known state.
LANG=C
LC_ALL=C
PAGER=cat
TZ=UTC
TERM=dumb
EDITOR=:
export LANG LC_ALL PAGER TZ TERM EDITOR
unset VISUAL CDPATH GREP_OPTIONS
# Line feed
LF='
'
[ "x$ORIGINAL_TERM" != "xdumb" ] && (
TERM=$ORIGINAL_TERM &&
export TERM &&
[ -t 1 ] &&
tput bold >/dev/null 2>&1 &&
tput setaf 1 >/dev/null 2>&1 &&
tput sgr0 >/dev/null 2>&1
) &&
color=t
while test "$#" -ne 0; do
case "$1" in
-d|--d|--de|--deb|--debu|--debug)
debug=t; shift ;;
-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
immediate=t; shift ;;
-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
TEST_LONG=t; export TEST_LONG; shift ;;
-h|--h|--he|--hel|--help)
help=t; shift ;;
-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
verbose=t; shift ;;
-q|--q|--qu|--qui|--quie|--quiet)
# Ignore --quiet under a TAP::Harness. Saying how many tests
# passed without the ok/not ok details is always an error.
test -z "$HARNESS_ACTIVE" && quiet=t; shift ;;
--no-color)
color=; shift ;;
--root=*)
root=$(expr "z$1" : 'z[^=]*=\(.*\)')
shift ;;
*)
echo "error: unknown test option '$1'" >&2; exit 1 ;;
esac
done
if test -n "$color"; then
say_color() {
(
TERM=$ORIGINAL_TERM
export TERM
case "$1" in
error)
tput bold; tput setaf 1;; # bold red
skip)
tput setaf 4;; # blue
warn)
tput setaf 3;; # brown/yellow
pass)
tput setaf 2;; # green
info)
tput setaf 6;; # cyan
*)
test -n "$quiet" && return;;
esac
shift
printf "%s" "$*"
tput sgr0
echo
)
}
else
say_color() {
test -z "$1" && test -n "$quiet" && return
shift
printf "%s\n" "$*"
}
fi
error() {
say_color error "error: $*"
EXIT_OK=t
exit 1
}
say() {
say_color info "$*"
}
test -n "$test_description" || error "Test script did not set test_description."
if test "$help" = "t"; then
echo "$test_description"
exit 0
fi
exec 5>&1
exec 6<&0
if test "$verbose" = "t"; then
exec 4>&2 3>&1
else
exec 4>/dev/null 3>/dev/null
fi
test_failure=0
test_count=0
test_fixed=0
test_broken=0
test_success=0
die() {
code=$?
if test -n "$EXIT_OK"; then
exit $code
else
echo >&5 "FATAL: Unexpected exit with code $code"
exit 1
fi
}
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 prerequiste (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=" "
# 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
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
}
# 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 - $@"
}
test_failure_() {
test_failure=$(($test_failure + 1))
say_color error "not ok $test_count - $1"
shift
echo "$@" | sed -e 's/^/# /'
test "$immediate" = "" || { EXIT_OK=t; exit 1; }
}
test_known_broken_ok_() {
test_fixed=$(($test_fixed + 1))
say_color error "ok $test_count - $@ # TODO known breakage vanished"
}
test_known_broken_failure_() {
test_broken=$(($test_broken + 1))
say_color warn "not ok $test_count - $@ # 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"
}
test_eval_() {
# This is a separate function because some tests use
# "return" to end a test_expect_success block early.
eval </dev/null >&3 2>&4 "$*"
}
test_run_() {
test_cleanup=:
expecting_failure=$2
test_eval_ "$1"
eval_ret=$?
if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"; then
test_eval_ "$test_cleanup"
fi
if test "$verbose" = "t" && test -n "$HARNESS_ACTIVE"; then
echo ""
fi
return "$eval_ret"
}
test_skip_() {
test_count=$(($test_count + 1))
to_skip=
for skp in $SKIP_TESTS; do
case $this_test.$test_count in
$skp)
to_skip=t
break
esac
done
if test -z "$to_skip" && test -n "$test_prereq" && ! test_have_prereq "$test_prereq"; then
to_skip=t
fi
case "$to_skip" in
t)
of_prereq=
if test "$missing_prereq" != "$test_prereq"; then
of_prereq=" of $test_prereq"
fi
say_color skip >&3 "skipping test: $@"
say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
: true
;;
*)
false
;;
esac
}
# Public: Run test commands and expect them to succeed.
#
# When the test passed, an "ok" message is printed and the number of successful
# tests is incremented. When it failed, a "not ok" message is printed and the
# number of failed tests is incremented.
#
# With --immediate, exit test immediately upon the first failed test.
#
# Usually takes two arguments:
# $1 - Test description
# $2 - Commands to be executed.
#
# With three arguments, the first will be taken to be a prerequisite:
# $1 - Comma-separated list of test prerequisites. The test will be skipped if
# not all of the given prerequisites are set. To negate a prerequisite,
# put a "!" in front of it.
# $2 - Test description
# $3 - Commands to be executed.
#
# Examples
#
# test_expect_success \
# 'git-write-tree should be able to write an empty tree.' \
# 'tree=$(git-write-tree)'
#
# # Test depending on one prerequisite.
# test_expect_success TTY 'git --paginate rev-list uses a pager' \
# ' ... '
#
# # Multiple prerequisites are separated by a comma.
# test_expect_success PERL,PYTHON 'yo dawg' \
# ' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" '
#
# Returns nothing.
test_expect_success() {
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_success"
export test_prereq
if ! test_skip_ "$@"; then
say >&3 "expecting success: $2"
if test_run_ "$2"; then
test_ok_ "$1"
else
test_failure_ "$@"
fi
fi
echo >&3 ""
}
# Public: Run test commands and expect them to fail. Used to demonstrate a known
# breakage.
#
# This is NOT the opposite of test_expect_success, but rather used to mark a
# test that demonstrates a known breakage.
#
# When the test passed, an "ok" message is printed and the number of fixed tests
# is incremented. When it failed, a "not ok" message is printed and the number
# of tests still broken is incremented.
#
# Failures from these tests won't cause --immediate to stop.
#
# Usually takes two arguments:
# $1 - Test description
# $2 - Commands to be executed.
#
# With three arguments, the first will be taken to be a prerequisite:
# $1 - Comma-separated list of test prerequisites. The test will be skipped if
# not all of the given prerequisites are set. To negate a prerequisite,
# put a "!" in front of it.
# $2 - Test description
# $3 - Commands to be executed.
#
# Returns nothing.
test_expect_failure() {
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
test "$#" = 2 || error "bug in the test script: not 2 or 3 parameters to test_expect_failure"
export test_prereq
if ! test_skip_ "$@"; then
say >&3 "checking known breakage: $2"
if test_run_ "$2" expecting_failure; then
test_known_broken_ok_ "$1"
else
test_known_broken_failure_ "$1"
fi
fi
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 comparision; 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: 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: Summarize test results and exit with an appropriate error code.
#
# Must be called at the end of each test script.
#
# Can also be used to stop tests early and skip all remaining tests. For this,
# set skip_all to a string explaining why the tests were skipped before calling
# test_done.
#
# Examples
#
# # Each test script must call test_done at the end.
# test_done
#
# # 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 tests passed or 1 if there was a failure.
test_done() {
EXIT_OK=t
if test -z "$HARNESS_ACTIVE"; then
test_results_dir="$SHARNESS_TEST_DIRECTORY/test-results"
mkdir -p "$test_results_dir"
test_results_path="$test_results_dir/${SHARNESS_TEST_FILE%.$SHARNESS_TEST_EXTENSION}.$$.counts"
cat >>"$test_results_path" <<-EOF
total $test_count
success $test_success
fixed $test_fixed
broken $test_broken
failed $test_failure
EOF
fi
if test "$test_fixed" != 0; then
say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
fi
if test "$test_broken" != 0; then
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 ))
msg="remaining $test_remaining test(s)"
else
test_remaining=$test_count
msg="$test_count 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
say_color pass "# passed all $msg"
fi
say "1..$test_count$skip_all"
test -d "$remove_trash" &&
cd "$(dirname "$remove_trash")" &&
rm -rf "$(basename "$remove_trash")"
exit 0 ;;
*)
say_color error "# failed $test_failure among $msg"
say "1..$test_count"
exit 1 ;;
esac
}
# Public: Root directory containing tests. Tests can override this variable,
# e.g. for testing Sharness itself.
: ${SHARNESS_TEST_DIRECTORY:=$(pwd)}
export 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/.."}
PATH="$SHARNESS_BUILD_DIRECTORY:$PATH"
export PATH SHARNESS_BUILD_DIRECTORY
# Public: Path to test script currently executed.
SHARNESS_TEST_FILE="$0"
export SHARNESS_TEST_FILE
# Prepare test area.
test_dir="trash directory.$(basename "$SHARNESS_TEST_FILE" ".$SHARNESS_TEST_EXTENSION")"
test -n "$root" && test_dir="$root/$test_dir"
case "$test_dir" in
/*) SHARNESS_TRASH_DIRECTORY="$test_dir" ;;
*) SHARNESS_TRASH_DIRECTORY="$SHARNESS_TEST_DIRECTORY/$test_dir" ;;
esac
test "$debug" = "t" || remove_trash="$SHARNESS_TRASH_DIRECTORY"
rm -rf "$test_dir" || {
EXIT_OK=t
echo >&5 "FATAL: Cannot prepare test area"
exit 1
}
# Public: Empty trash directory, the test area, provided for each test. The HOME
# variable is set to that directory too.
export SHARNESS_TRASH_DIRECTORY
HOME="$SHARNESS_TRASH_DIRECTORY"
export HOME
mkdir -p "$test_dir" || 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 "$test_dir" || exit 1
this_test=${SHARNESS_TEST_FILE##*/}
this_test=${this_test%.$SHARNESS_TEST_EXTENSION}
for skp in $SKIP_TESTS; do
case "$this_test" in
$skp)
say_color info >&3 "skipping test $this_test altogether"
skip_all="skip all tests in $this_test"
test_done
esac
done
# vi: set ts=4 sw=4 noet :

View File

@@ -1,12 +0,0 @@
#!/bin/sh
. ./sharness.sh
test_set_prereq PYTHON
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

1
tools/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
results.txt

198
tools/check-versions Executable file
View File

@@ -0,0 +1,198 @@
#!/usr/bin/env ruby
#
# Copyright (c) 2019-2023 Felipe Contreras
#
# This script runs the tests for all versions of hg.
#
# You can run it without arguments, in which case it runs the tests for all
# versions in `versions.txt`.
#
# Or you can specify a single version manually:
#
# ./check-versions 6.3
#
require 'fileutils'
require 'tmpdir'
$tests = %w[main.t bidi.t hg-git.t]
$workdir = "#{Dir.home}/.cache/git-remote-hg"
$builddir = Dir.mktmpdir("git-remote-hg-build-")
$testoutdir = Dir.mktmpdir("git-remote-hg-tests-")
at_exit {
FileUtils.remove_entry($builddir)
FileUtils.remove_entry($testoutdir)
}
QUIET, LOW, HIGH = (1..3).to_a
$verbosity = LOW
# Util {{{1
def section(text)
puts [nil, text, '=' * text.size]
end
def title(text)
puts [nil, text, '-' * text.size] unless $verbosity < HIGH
end
def run_cmd(cmd, fatal: true)
puts cmd.join(' ') unless $verbosity < HIGH
result = system(*cmd)
unless result or not fatal
STDERR.puts "Failed to run command '%s'" % cmd.join(' ')
exit -1
end
result
end
def check_version(a, b)
return true if a == '@'
a = a.split('.').map(&:to_i)
b = b.split('.').map(&:to_i)
(a <=> b) >= 0
end
# Hg {{{1
class Hg
def initialize
@url = 'https://www.mercurial-scm.org/repo/hg'
end
def dir
"#{$workdir}/hg"
end
def clone
run_cmd %w[hg clone -q] + [@url, dir]
end
def checkout(version)
Dir.chdir(dir) do
run_cmd %w[hg update --clean -q] << version
checkout_fix(version)
end
end
def build
Dir.chdir(dir) do
targets = %w[build_py build_ext].map { |e| [e, '--build-lib', "#{$builddir}/python"] }
run_cmd %w[python setup.py --quiet] + targets.flatten
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
def setup
dirs = %w[bin python]
FileUtils.mkdir_p(dirs.map { |e| "#{$builddir}/#{e}" })
FileUtils.mkdir_p($workdir)
return if File.exist?($hg.dir)
if $verbosity < HIGH
puts "Cloning hg"
else
title "Cloning hg"
end
$hg.clone
end
def test_env(paths: nil)
old = ENV.to_h
paths.each do |id, path|
name = id.to_s
ENV[name] = "#{path}:#{ENV[name]}"
end
r = yield
ENV.replace(old)
return r
end
def run_tests(tests)
title "Running tests"
Dir.chdir("#{__dir__}/../test") do
case $verbosity
when QUIET
tests_opt = tests.join(' ')
cmd = "prove -q #{tests_opt} :: -i"
when LOW
tests_opt = "T='%s'" % tests.join(' ')
cmd = "make -j1 #{tests_opt}"
else
tests_opt = "T='%s'" % tests.join(' ')
cmd = "TEST_OPTS='-v -i' make -j1 #{tests_opt}"
end
system(cmd)
end
end
def check(version)
section version
title "Checking out hg #{version}"
$hg.checkout(version)
title "Building hg"
$hg.build
paths = {
PATH: "#{$builddir}/bin",
PYTHONPATH: "#{$builddir}/python",
}
test_env(paths: paths) do
ENV['SHARNESS_TEST_OUTPUT_DIRECTORY'] = $testoutdir
run_tests($tests)
end
end
$hg = Hg.new()
# Main {{{1
setup
$checks = []
$version = ARGV.first
$checks = File.readlines(__dir__ + '/versions.txt', chomp: true)
$results = File.open(__dir__ + '/results.txt', 'w')
if $version
$verbosity = HIGH
exit check($version) ? 0 : 1
else
$verbosity = QUIET
failures = 0
$checks.each do |version|
result = check(version)
failures += 1 unless result
$results.puts '%s # %s' % [version, result ? 'OK' : 'FAIL']
end
exit 1 unless failures == 0
end

View File

@@ -0,0 +1,15 @@
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -181,7 +181,10 @@
# error 0xc0150004. See: http://bugs.python.org/issue3440
env['SystemRoot'] = os.environ['SystemRoot']
-if os.path.isdir('.hg'):
+if os.path.exists('.hg_force_version'):
+ with open('.hg_force_version') as f:
+ version = f.read().rstrip('\n')
+elif os.path.isdir('.hg'):
cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()

47
tools/versions.txt Normal file
View File

@@ -0,0 +1,47 @@
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