261 Commits
v0.4 ... v1.0.5

Author SHA1 Message Date
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
43 changed files with 3485 additions and 1137 deletions

27
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: CI
on:
# push:
# 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' ]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.10'
- uses: actions/cache@v3
id: cache-pip
with:
path: ~/.cache/pip
key: pip
- name: Install hg
run:
pip install mercurial==${{ matrix.hg }}
- run: make test

3
.gitignore vendored Normal file
View File

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

View File

@@ -1,28 +0,0 @@
language: python
install:
- if [ "$HG_VERSION" != "dev" ];
then pip install -q Mercurial${HG_VERSION+==$HG_VERSION};
else pip install -q http://selenic.com/repo/hg/archive/tip.tar.gz;
fi
- pip install -q dulwich hg-git==0.6.1 || true
before_script:
- hg --version || true
- pip show hg-git dulwich
script:
- make test
matrix:
include:
- env: HG_VERSION=2.9.1
- env: HG_VERSION=2.8.2
- env: HG_VERSION=2.7.2
- env: HG_VERSION=3.0
- env: HG_VERSION=3.5.2
- env: HG_VERSION=3.6.3
- env: HG_VERSION=3.7
- env: HG_VERSION=dev
- python: 2.7
- python: 2.6

View File

@@ -3,7 +3,28 @@ prefix := $(HOME)
bindir := $(prefix)/bin
mandir := $(prefix)/share/man/man1
all: doc
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
@@ -11,19 +32,33 @@ test:
$(MAKE) -C test
doc/git-remote-hg.1: doc/git-remote-hg.txt
a2x -d manpage -f manpage $<
asciidoctor -d manpage -b manpage $<
clean:
$(RM) doc/git-remote-hg.1
$(RM) -r bin/
D = $(DESTDIR)
install:
install: build
install -d -m 755 $(D)$(bindir)/
install -m 755 git-remote-hg $(D)$(bindir)/git-remote-hg
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
.PHONY: all test install install-doc clean
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

View File

@@ -1,4 +1,4 @@
'git-remote-hg' is the semi-official Mercurial bridge from Git project, once
`git-remote-hg` is the semi-official Mercurial bridge from the Git project, once
installed, it allows you to clone, fetch and push to and from Mercurial
repositories as if they were Git ones:
@@ -6,13 +6,20 @@ repositories as if they were Git ones:
git clone "hg::http://selenic.com/repo/hello"
--------------------------------------
To enable this, simply add the 'git-remote-hg' script anywhere in your `$PATH`:
To enable this, simply add the `git-remote-hg` script anywhere in your `$PATH`:
--------------------------------------
wget https://raw.github.com/mnauw/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg
wget https://raw.githubusercontent.com/mnauw/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg
chmod +x ~/bin/git-remote-hg
--------------------------------------
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.
@@ -42,7 +49,8 @@ If you want to see Mercurial revisions as Git commit notes:
% git config core.notesRef refs/notes/hg
--------------------------------------
If you are not interested in Mercurial permanent and global branches (aka. commit labels):
If you are not interested in Mercurial permanent and global branches (aka.
commit labels):
--------------------------------------
% git config --global remote-hg.track-branches false
@@ -50,29 +58,47 @@ If you are not interested in Mercurial permanent and global branches (aka. commi
With this configuration, the 'branches/foo' refs won't appear.
If you want the equivalent of 'hg clone --insecure':
If you want the equivalent of `hg clone --insecure`:
--------------------------------------
% git config --global remote-hg.insecure true
--------------------------------------
If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly the same commits:
If you want `git-remote-hg` to be compatible with `hg-git`, and generate exactly
the same commits:
--------------------------------------
% git config --global remote-hg.hg-git-compat true
--------------------------------------
****
mnauw's note; The above is not quite the case, it only ever has been (somewhat)
if an undocumented debug mode (`debugextrainmessage` setting) was enabled
in (likely somewhat patched) `hg-git`. And as of `hg-git` v1.2.0 the latter is
no longer considered. In fact, `hg-git` creates git commits with additional hg
metadata stored in so-called "extra commit headers". The latter might be seen by
`git log --format=raw` or `git cat-file -p <commitid>`, but are otherwise mostly
only used internally by the git suite (for signatures). While they are supported
by `dulwich`'s API (which is a python git implementation), there is, however,
limited to no support for those in git "porcelain or plumbing" commands. In
particular, `git fast-export` and `git fast-import` do not consider these, so a
`gitremote-helpers` tool is then also out of luck. Incidentally, it also
follows that a `git fast-export | git fast-import` "clone" approach would also
lose such extra metadata, and likewise so for e.g. `git filter-repo`.
All in all, this mode is not quite recommended.
If the concern here is not so much `hg-git` compatibility but rather "hg-git-hg
round-trip fidelity", then see the discussion below on `check-hg-commits` setting.
****
== Notes ==
Remember to run `git gc --aggressive` after cloning a repository, specially if
Remember to run `git gc --aggressive` after cloning a repository, especially if
it's a big one. Otherwise lots of space will be wasted.
The oldest version of mercurial supported is 1.9. For the most part 1.8 works,
but you might experience some issues.
=== Pushing branches ===
To push a branch, you need to use the "branches/" prefix:
To push a branch, you need to use the 'branches/' prefix:
--------------------------------------
% git checkout branches/next
@@ -82,7 +108,7 @@ To push a branch, you need to use the "branches/" prefix:
All the pushed commits will receive the "next" Mercurial named branch.
*Note*: Make sure you don't have +remote-hg.track-branches+ disabled.
*Note*: Make sure you don't have `remote-hg.track-branches` disabled.
=== Cloning HTTPS ===
@@ -92,7 +118,7 @@ The simplest way is to specify the user and password in the URL:
git clone hg::https://user:password@bitbucket.org/user/repo
--------------------------------------
You can also use the http://mercurial.selenic.com/wiki/SchemesExtension[schemes extension]:
You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]:
--------------------------------------
[auth]
@@ -102,11 +128,7 @@ bb.password = password
--------------------------------------
Finally, you can also use the
https://pypi.python.org/pypi/mercurial_keyring[keyring extension].
However, some of these features require very new versions of 'git-remote-hg',
so you might have better luck simply specifying the username and password in
the URL.
https://pypi.org/project/mercurial_keyring[keyring extension].
=== Submodules ===
@@ -134,10 +156,10 @@ Mercurial branches and bookmarks have some limitations of Git branches: you
can't have both 'dev/feature' and 'dev' (as Git uses files and directories to
store them).
Multiple anonymous heads (which are useless anyway) are not supported; you
Multiple anonymous heads (which are useless anyway) are not supported: you
would only see the latest head.
Closed branches are not supported; they are not shown and you can't close or
Closed branches are not supported: they are not shown and you can't close or
reopen. Additionally in certain rare situations a synchronization issue can
occur (https://github.com/felipec/git/issues/65[Bug #65]).
@@ -146,8 +168,6 @@ Limitations of the remote-helpers' framework apply. In particular, these
commands don't work:
* `git push origin :branch-to-delete`
* `git push origin old:new` (it will push 'old') (patches available)
* `git push --dry-run origin branch` (it will push) (patches available)
****
Another limitation is that if `git log` reports a rename, this will not survive
@@ -165,16 +185,27 @@ below for more details.
== Other projects ==
There are other 'git-remote-hg' projects out there, do not confuse this one,
this is the one distributed officially by the Git project
(_though actually no longer so nowadays_):
There are other `git-remote-hg` projects out there, but this is the original,
which was distributed officially in the Git project.
* https://github.com/msysgit/msysgit/wiki/Guide-to-git-remote-hg[msysgit's git-remote-hg]
* https://github.com/rfk/git-remote-hg[rfk's git-remote-hg]
Over the years many similar tools have died out, the only actively maintained
alternative is mnauw's fork of this project:
https://github.com/mnauw/git-remote-hg[mnauw/git-remote-hg]. I've merged some of
his patches, and he has merged some of my patches, so the projects are mostly in
sync, but not quite. In particular Nauwelaerts' fork has many administrative
extensions, which although useful to some people, I don't believe they belong
in the core.
For a comparison between these and other projects go
https://github.com/felipec/git/wiki/Comparison-of-git-remote-hg-alternatives[here].
****
mnauw's note; I do not know what "the core" means?
However, the "extensions" provide useful and possibly
critical maintenance wrt git-remote-hg's internal data, so it belongs as close
to the latter one as possible.
****
[[no-limitations]]
== Limitations (or not) ==
@@ -247,9 +278,11 @@ 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). So, pending some
"nice" bidirectional encoding (not even e.g. URL encoding is safe actually), it is more
likely that only a few instances (out of a whole Mercurial repo) are
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
@@ -354,7 +387,8 @@ up elsewhere as expected (regardless of conversion mapping or ABI).
Note that identifying and re-using the hg changeset relies on metadata
(`refs/notes/hg` and marks files) that is not managed or maintained by any
git-to-git fetch (or clone).
git-to-git fetch (or clone) (as that is only automatically so for `refs/heads/`,
though it could be pushed manually).
As such (and as said), this approach aims for plain-and-simple safety, but only
within a local scope (git repo).

View File

@@ -38,7 +38,8 @@ If you want to see Mercurial revisions as Git commit notes:
% git config core.notesRef refs/notes/hg
--------------------------------------
If you are not interested in Mercurial permanent and global branches (aka. commit labels):
If you are not interested in Mercurial permanent and global branches (aka.
commit labels):
--------------------------------------
% git config --global remote-hg.track-branches false
@@ -52,7 +53,8 @@ If you want the equivalent of `hg clone --insecure`:
% git config --global remote-hg.insecure true
--------------------------------------
If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly the same commits:
If you want 'git-remote-hg' to be compatible with 'hg-git', and generate exactly
the same commits:
--------------------------------------
% git config --global remote-hg.hg-git-compat true
@@ -102,19 +104,32 @@ the invalid '~'
% git config --global remote-hg.ignore-name ~
--------------------------------------
Even though the "gitdir" is configurable (using `GIT_DIR`), git does not accept
certain pathname components, e.g. `.git` or `.gitmodules` (case-insensitive).
Problems arise if the hg repo contains such pathnames, and recent git versions
will reject this in a very hard way. So these pathnames are now mapped
from "hg space" to "git space" in a one-to-one way, where (e.g.)
`.git[0 or more suffix]` is mapped to `.git[1 or more suffix]` (obviously by
appending or removing a suffix). The "suffix" in question defaults to `_`,
but can be configured using
--------------------------------------
% git config --global remote-hg.dotfile-suffix _
--------------------------------------
NOTES
-----
Remember to run `git gc --aggressive` after cloning a repository, specially if
Remember to run `git gc --aggressive` after cloning a repository, especially if
it's a big one. Otherwise lots of space will be wasted.
The oldest version of Mercurial supported is 1.9. For the most part 1.8 works,
but you might experience some issues.
The newest supported version of Mercurial is 6.2, the oldest one is 2.4.
Pushing branches
~~~~~~~~~~~~~~~~
To push a Mercurial named branch, you need to use the "branches/" prefix:
To push a branch, you need to use the "branches/" prefix:
--------------------------------------
% git checkout branches/next
@@ -135,7 +150,7 @@ The simplest way is to specify the user and password in the URL:
git clone hg::https://user:password@bitbucket.org/user/repo
--------------------------------------
You can also use the http://mercurial.selenic.com/wiki/SchemesExtension[schemes extension]:
You can also use the https://mercurial-scm.org/wiki/SchemesExtension[schemes extension]:
--------------------------------------
[auth]
@@ -145,7 +160,7 @@ bb.password = password
--------------------------------------
Finally, you can also use the
https://pypi.python.org/pypi/mercurial_keyring[keyring extension].
https://pypi.org/project/mercurial_keyring[keyring extension].
CAVEATS
-------
@@ -157,10 +172,10 @@ Mercurial branches and bookmarks have some limitations of Git branches: you
can't have both 'dev/feature' and 'dev' (as Git uses files and directories to
store them).
Multiple anonymous heads (which are useless anyway) are not supported; you
Multiple anonymous heads (which are useless anyway) are not supported: you
would only see the latest head.
Closed branches are not supported; they are not shown and you can't close or
Closed branches are not supported: they are not shown and you can't close or
reopen. Additionally in certain rare situations a synchronization issue can
occur (https://github.com/felipec/git/issues/65[Bug #65]).

View File

@@ -1,10 +1,15 @@
#!/usr/bin/env python2
#!/usr/bin/env python
#
# Copyright (c) 2016 Mark Nauwelaerts
#
from mercurial import hg, ui, commands, util
from mercurial import context, subrepo
try:
# hg >= 5.8
from mercurial.utils import urlutil
except ImportError:
from mercurial import util as urlutil
import re
import sys
@@ -16,13 +21,72 @@ import logging
import threading
# thanks go to git-remote-helper for some helper functions
# likewise so for python2/3 compatibility
def die(msg, *args):
sys.stderr.write('ERROR: %s\n' % (msg % args))
# generic
class basecompat:
@staticmethod
def char(c):
assert len(c) == 1
return c[0]
if sys.version_info[0] == 3:
import locale
class compat(basecompat):
# sigh ... wonderful python3 ... as taken from Mercurial's pycompat
@staticmethod
def decode_sysarg(arg):
if os.name == r'nt':
return arg.encode("mbcs", "ignore")
else:
enc = (
locale.getlocale()[1]
or locale.getdefaultlocale()[1]
or sys.getfilesystemencoding()
)
return arg.encode(enc, "surrogateescape")
# mostly used for straight 'cast' (not real unicode content)
@staticmethod
def to_b(s, *args):
if isinstance(s, str):
args = args or ['latin-1']
return s.encode(*args)
return s
stdin = sys.stdin.buffer
stdout = sys.stdout.buffer
stderr = sys.stderr.buffer
getcwd = os.getcwdb
@staticmethod
def getenvb(val, default):
result = os.getenv(val.decode(), default.decode() if hasattr(default, 'decode') else default)
# if result is a string, get bytes instead
result = result.encode() if hasattr(result, 'encode') else result
return result
getenv = os.getenvb if os.supports_bytes_environ else getenvb
else:
class compat(basecompat):
# life was simple in those days ...
@staticmethod
def to_b(s, *args):
return s
decode_sysarg = to_b
stdin = sys.stdin
stdout = sys.stdout
stderr = sys.stderr
getcwd = staticmethod(os.getcwd)
getenv = staticmethod(os.getenv)
def puts(msg = b''):
compat.stdout.write(msg)
compat.stdout.write(b'\n')
def die(msg):
compat.stderr.write(b'ERROR: %s\n' % compat.to_b(msg, 'utf-8'))
sys.exit(1)
def warn(msg, *args):
sys.stderr.write('WARNING: %s\n' % (msg % args))
def warn(msg):
compat.stderr.write(b'WARNING: %s\n' % compat.to_b(msg, 'utf-8'))
compat.stderr.flush()
def info(msg, *args):
logger.info(msg, *args)
@@ -33,18 +97,34 @@ def debug(msg, *args):
def log(msg, *args):
logger.log(logging.LOG, msg, *args)
# new style way to import a source file
def _imp_load_source(module_name, file_path):
import importlib.util
loader = importlib.machinery.SourceFileLoader(module_name, file_path)
spec = importlib.util.spec_from_loader(module_name, loader)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
return module
def import_sibling(mod, filename):
import imp
mydir = os.path.dirname(__file__)
sys.dont_write_bytecode = True
return imp.load_source(mod, os.path.join(mydir, filename))
vi = sys.version_info
ff = os.path.join(mydir, filename)
if vi.major >= 3 and vi.minor >= 5:
return _imp_load_source(mod, ff)
else:
import imp
return imp.load_source(mod, ff)
class GitHgRepo:
def __init__(self, topdir=None, gitdir=None):
if gitdir != None:
self.gitdir = gitdir
self.topdir = os.path.join(gitdir, '..') # will have to do
self.topdir = os.path.join(gitdir, b'..') # will have to do
else:
self.topdir = None
if not topdir:
@@ -53,7 +133,7 @@ class GitHgRepo:
if not os.path.exists('.git'):
# now we lost where we are
raise Exception('failed to determine topdir')
topdir = '.'
topdir = b'.'
self.topdir = topdir
self.gitdir = self.run_cmd(['rev-parse', '--git-dir']).strip()
if not self.gitdir:
@@ -64,7 +144,7 @@ class GitHgRepo:
self.hg_repos = {}
def identity(self):
return '[%s|%s]' % (os.getcwd(), self.topdir)
return b'[%s|%s]' % (compat.getcwd(), self.topdir or b'')
def start_cmd(self, args, **kwargs):
cmd = ['git'] + args
@@ -82,7 +162,7 @@ class GitHgRepo:
process = self.start_cmd(args, **kwargs)
output = process.communicate()[0]
if check and process.returncode != 0:
die('command failed: %s', ' '.join(cmd))
die(b'git command failed: %s' % b' '.join([compat.to_b(a) for a in args]))
return output
def get_config(self, config, getall=False):
@@ -91,17 +171,17 @@ class GitHgRepo:
return self.run_cmd(['config', get[getall] , config], stderr=None)
def get_config_bool(self, config, default=False):
value = self.get_config(config).rstrip('\n')
if value == "true":
value = self.get_config(config).rstrip()
if value == b"true":
return True
elif value == "false":
elif value == b"false":
return False
else:
return default
def get_hg_repo_url(self, remote):
url = self.get_config('remote.%s.url' % (remote))
if url and url[0:4] == 'hg::':
url = self.get_config(b'remote.%s.url' % (remote))
if url and url[0:4] == b'hg::':
url = url[4:].strip()
else:
url = None
@@ -129,9 +209,9 @@ class GitHgRepo:
for r in self.get_hg_repos():
try:
hgpath = remotehg.select_marks_dir(r, self.gitdir, False)
m = remotehg.Marks(os.path.join(hgpath, 'marks-hg'), None)
m = remotehg.Marks(os.path.join(hgpath, b'marks-hg'), None)
mark = m.from_rev(rev)
m = GitMarks(os.path.join(hgpath, 'marks-git'))
m = GitMarks(os.path.join(hgpath, b'marks-git'))
return m.to_rev(mark)
except:
pass
@@ -143,29 +223,32 @@ class GitHgRepo:
return self.hg_repos
# check any local hg repo to see if rev is in there
shared_path = os.path.join(self.gitdir, 'hg')
hg_path = os.path.join(shared_path, '.hg')
shared_path = os.path.join(self.gitdir, b'hg')
hg_path = os.path.join(shared_path, b'.hg')
if os.path.exists(shared_path):
repos = os.listdir(shared_path)
for r in repos:
# skip the shared repo
if r == '.hg':
if r == b'.hg':
continue
# only dirs
if not os.path.isdir(os.path.join(shared_path, r)):
continue
local_path = os.path.join(shared_path, r, 'clone')
local_hg = os.path.join(local_path, '.hg')
local_path = os.path.join(shared_path, r, b'clone')
local_hg = os.path.join(local_path, b'.hg')
if not os.path.exists(local_hg):
# could be a local repo without proxy, fetch url
local_path = self.get_hg_repo_url(r)
if not local_path:
warn('failed to find local hg for remote %s', r)
warn(b'failed to find local hg for remote %s' % (r))
continue
else:
npath = os.path.abspath(hg_path)
# use relative path if possible
if check_version(4, 2):
npath = os.path.join(b'..', b'..', b'..', b'.hg')
# make sure the shared path is always up-to-date
util.writefile(os.path.join(local_hg, 'sharedpath'),
os.path.abspath(hg_path))
util.writefile(os.path.join(local_hg, b'sharedpath'), npath)
self.hg_repos[r] = os.path.join(local_path)
log('%s determined hg_repos %s', self.identity(), self.hg_repos)
@@ -176,9 +259,9 @@ class GitHgRepo:
repos = self.get_hg_repos()
if r in repos:
local_path = repos[r]
hushui = ui.ui()
hushui.setconfig('ui', 'interactive', 'off')
hushui.fout = open(os.devnull, 'w')
hushui = ui.ui.load() if hasattr(ui.ui, 'load') else ui.ui()
hushui.setconfig(b'ui', b'interactive', b'off')
hushui.fout = open(os.devnull, 'wb')
return hg.repository(hushui, local_path)
def find_hg_repo(self, rev):
@@ -201,7 +284,7 @@ class GitHgRepo:
def __init__(self, repo, files):
p1, p2, data = repo[None], '0' * 40, ''
context.memctx.__init__(self, repo, (p1, p2),
data, files.keys(), self.getfilectx)
data, list(files.keys()), self.getfilectx)
self.files = files
self.remotehg = import_sibling('remotehg', 'git-remote-hg')
self.remotehg.hg_version = hg_version
@@ -215,13 +298,13 @@ class GitHgRepo:
is_link, is_exec, rename)
def read(self, relpath, rev=None):
rev = rev if rev else ':0'
obj = '%s:%s' % (rev, relpath)
rev = rev if rev else b':0'
obj = b'%s:%s' % (rev, relpath)
# might complain bitterly to stderr if no subrepos so let's not show that
return self.run_cmd(['show', obj])
# see also subrepo.state
def state(self, remote='origin', rev=None):
def state(self, remote=b'origin', rev=None):
"""return a state dict, mapping subrepo paths configured in .hgsub
to tuple: (source from .hgsub, revision from .hgsubstate, kind
(key in types dict))
@@ -229,7 +312,7 @@ class GitHgRepo:
# obtain relevant files' content from specified revision
files = { }
for f in ('.hgsub', '.hgsubstate'):
for f in (b'.hgsub', b'.hgsubstate'):
files[f] = self.read(f)
log('state files for %s in revision %s:\n%s', remote, rev, files)
@@ -237,7 +320,7 @@ class GitHgRepo:
# (rather than duplicating the admittedly simple parsing here)
repo = self.get_hg_repo(remote)
if not repo:
die('no hg repo for alias %s' % remote)
die(b'no hg repo for alias %s' % remote)
ctx = self.dictmemctx(repo, files)
# helpers moved around 4.6
if hasattr(subrepo, 'state'):
@@ -252,21 +335,21 @@ class GitHgRepo:
resolved = {}
for s in state:
src, rev, kind = state[s]
if not kind in ('hg', 'git'):
if not kind in (b'hg', b'git'):
warn('skipping unsupported subrepo type %s' % kind)
continue
if not util.url(src).isabs():
if not urlutil.url(src).isabs():
parent = self.get_hg_repo_url(remote)
if not parent:
die('could not determine repo url of %s' % remote)
parent = util.url(parent)
parent.path = posixpath.join(parent.path or '', src)
die(b'could not determine repo url of %s' % remote)
parent = urlutil.url(parent)
parent.path = posixpath.join(parent.path or b'', src)
parent.path = posixpath.normpath(parent.path)
src = str(parent)
src = bytes(parent)
# translate to git view url
if kind == 'hg':
src = 'hg::' + src
resolved[s] = (src.strip(), rev or '', kind)
if kind == b'hg':
src = b'hg::' + src
resolved[s] = (src.strip(), rev or b'', kind)
log('resolved state %s', resolved)
return resolved
@@ -277,12 +360,15 @@ class SubCommand:
self.subcommand = subcmdname
self.githgrepo = githgrepo
self.argparser = self.argumentparser()
# list of str
self.args = []
def argumentparser(self):
return argparse.ArgumentParser()
def get_remote(self, args):
if len(args):
assert isinstance(args[0], bytes)
return (args[0], args[1:])
else:
self.usage('missing argument: <remote-alias>')
@@ -295,7 +381,7 @@ class SubCommand:
def execute(self, args):
(self.options, self.args) = self.argparser.parse_known_args(args)
self.do(self.options, self.args)
self.do(self.options, [compat.decode_sysarg(a) for a in self.args])
def usage(self, msg):
if msg:
@@ -304,6 +390,7 @@ class SubCommand:
self.argparser.print_usage(sys.stderr)
sys.exit(2)
# args: list of bytes
def do(self, options, args):
pass
@@ -322,7 +409,7 @@ class HgRevCommand(SubCommand):
if len(args):
hgrev = self.githgrepo.get_hg_rev(args[0])
if hgrev:
print hgrev
puts(hgrev)
class GitMarks:
@@ -340,24 +427,24 @@ class GitMarks:
if not os.path.exists(self.path):
return
for l in file(self.path):
m, c = l.strip().split(' ', 2)
for l in open(self.path, 'rb'):
m, c = l.strip().split(b' ', 2)
m = int(m[1:])
self.marks[c] = m
self.rev_marks[m] = c
def store(self):
marks = self.rev_marks.keys()
marks = list(self.rev_marks.keys())
marks.sort()
with open(self.path, 'w') as f:
with open(self.path, 'wb') as f:
for m in marks:
f.write(':%d %s\n' % (m, self.rev_marks[m]))
f.write(b':%d %s\n' % (m, self.rev_marks[m]))
def from_rev(self, rev):
return self.marks[rev]
def to_rev(self, mark):
return str(self.rev_marks[mark])
return self.rev_marks[mark]
class GitRevCommand(SubCommand):
@@ -375,7 +462,7 @@ class GitRevCommand(SubCommand):
rev = args[0]
gitcommit = self.githgrepo.get_git_commit(rev)
if gitcommit:
print gitcommit
puts(gitcommit)
class GcCommand(SubCommand):
@@ -408,7 +495,7 @@ class GcCommand(SubCommand):
def print_commits(self, gm, dest):
for c in gm.marks.keys():
dest.write(c + '\n')
dest.write(c + b'\n')
dest.flush()
dest.close()
@@ -422,27 +509,27 @@ class GcCommand(SubCommand):
if not remote in hg_repos:
self.usage('%s is not a valid hg remote' % (remote))
hgpath = remotehg.select_marks_dir(remote, self.githgrepo.gitdir, False)
print "Loading hg marks ..."
hgm = remotehg.Marks(os.path.join(hgpath, 'marks-hg'), None)
print "Loading git marks ..."
gm = GitMarks(os.path.join(hgpath, 'marks-git'))
puts(b"Loading hg marks ...")
hgm = remotehg.Marks(os.path.join(hgpath, b'marks-hg'), None)
puts(b"Loading git marks ...")
gm = GitMarks(os.path.join(hgpath, b'marks-git'))
repo = hg.repository(ui.ui(), hg_repos[remote]) if options.check_hg else None
# git-gc may have dropped unreachable commits
# (in particular due to multiple hg head cases)
# need to drop those so git-fast-export or git-fast-import does not complain
print "Performing garbage collection on git commits ..."
puts(b"Performing garbage collection on git commits ...")
process = self.githgrepo.start_cmd(['cat-file', '--batch-check'], \
stdin=subprocess.PIPE)
thread = threading.Thread(target=self.print_commits, args=(gm, process.stdin))
thread.start()
git_marks = set({})
for l in process.stdout:
sp = l.strip().split(' ', 2)
sp = l.strip().split(b' ', 2)
if sp[1] == 'commit':
git_marks.add(gm.from_rev(sp[0]))
thread.join()
# reduce down to marks that are common to both
print "Computing marks intersection ..."
puts(b"Computing marks intersection ...")
common_marks = set(hgm.rev_marks.keys()).intersection(git_marks)
hg_rev_marks = {}
git_rev_marks = {}
@@ -453,7 +540,7 @@ class GcCommand(SubCommand):
git_rev_marks[m] = gm.rev_marks[m]
# common marks will not not include any refs/notes/hg
# let's not discard those casually, though they are not vital
print "Including notes commits ..."
puts(b"Including notes commits ...")
revlist = self.githgrepo.start_cmd(['rev-list', 'refs/notes/hg'])
for l in revlist.stdout.readlines():
c = l.strip()
@@ -465,35 +552,72 @@ class GcCommand(SubCommand):
git_rev_marks[hgm.last_note] = gm.rev_marks[hgm.last_note]
# some status report
if len(hgm.rev_marks) != len(hg_rev_marks):
print "Trimmed hg marks from #%d down to #%d" % (len(hgm.rev_marks), len(hg_rev_marks))
puts(b"Trimmed hg marks from #%d down to #%d" % (len(hgm.rev_marks), len(hg_rev_marks)))
if len(gm.rev_marks) != len(git_rev_marks):
print "Trimmed git marks from #%d down to #%d" % (len(gm.rev_marks), len(git_rev_marks))
puts(b"Trimmed git marks from #%d down to #%d" % (len(gm.rev_marks), len(git_rev_marks)))
# marks-hg tips irrelevant nowadays
# now update and store
if not options.dry_run:
# hg marks
print "Writing hg marks ..."
puts(b"Writing hg marks ...")
hgm.rev_marks = hg_rev_marks
hgm.marks = {}
for mark, rev in hg_rev_marks.iteritems():
for mark, rev in hg_rev_marks.items():
hgm.marks[rev] = mark
hgm.store()
# git marks
print "Writing git marks ..."
puts(b"Writing git marks ...")
gm.rev_marks = git_rev_marks
gm.marks = {}
for mark, rev in git_rev_marks.iteritems():
for mark, rev in git_rev_marks.items():
gm.marks[rev] = mark
gm.store()
class MapFileCommand(SubCommand):
def argumentparser(self):
usage = '%%(prog)s %s [options] <remote>' % (self.subcommand)
p = argparse.ArgumentParser(usage=usage)
p.add_argument('--output', required=True,
help='mapfile to write')
p.epilog = textwrap.dedent("""\
Writes a so-called git-mapfile, as used internally by hg-git.
This files consists of lines of format `<githexsha> <hghexsha>`.
As such, the result could be used to coax hg-git in some manner.
However, as git-remote-hg and hg-git may (likely) produce different
commits (either git or hg), mixed use of both tools is not recommended.
""")
return p
def do(self, options, args):
remotehg = import_sibling('remotehg', 'git-remote-hg')
if not args or len(args) != 1:
self.usage('expect 1 remote')
remote = args[0]
hgpath = remotehg.select_marks_dir(remote, self.githgrepo.gitdir, False)
puts(b"Loading hg marks ...")
hgm = remotehg.Marks(os.path.join(hgpath, b'marks-hg'), None)
puts(b"Loading git marks ...")
gm = GitMarks(os.path.join(hgpath, b'marks-git'))
puts(b"Writing mapfile ...")
with open(options.output, 'wb') as f:
for c, m in gm.marks.items():
hgc = hgm.rev_marks.get(m, None)
if hgc:
f.write(b'%s %s\n' % (c, hgc))
class SubRepoCommand(SubCommand):
def writestate(repo, state):
"""rewrite .hgsubstate in (outer) repo with these subrepo states"""
lines = ['%s %s\n' % (state[s][1], s) for s in sorted(state)
lines = [b'%s %s\n' % (state[s][1], s) for s in sorted(state)
if state[s][1] != nullstate[1]]
repo.wwrite('.hgsubstate', ''.join(lines), '')
repo.wwrite(b'.hgsubstate', b''.join(lines), b'')
def argumentparser(self):
#usage = '%%(prog)s %s [options] <remote>...' % (self.subcommand)
@@ -630,7 +754,8 @@ class SubRepoCommand(SubCommand):
if args:
# all arguments are registered, so should not have leftover
# could be that main arguments were given to subcommands
warn('unparsed arguments: %s' % ' '.join(args))
warn(b'unparsed arguments: %s' % b' '.join(args))
options.remote = compat.decode_sysarg(options.remote)
log('running subcmd options %s, args %s', options, args)
# establish initial operation ctx
ctx = self.subcontext(self.githgrepo)
@@ -640,10 +765,10 @@ class SubRepoCommand(SubCommand):
log('running %s with options %s in context %s', \
options.func, options, ctx)
subrepos = ctx.repo.state(options.remote)
paths = subrepos.keys()
paths = list(subrepos.keys())
selabspaths = None
if ctx.level == 0 and hasattr(options, 'paths') and options.paths:
selabspaths = [ os.path.abspath(p) for p in options.paths ]
selabspaths = [ os.path.abspath(compat.decode_sysarg(p)) for p in options.paths ]
log('level %s selected paths %s', ctx.level, selabspaths)
for p in paths:
# prep context
@@ -662,17 +787,17 @@ class SubRepoCommand(SubCommand):
if not ctx.subrepo:
ctx.subrepo = self.git_hg_repo_try(ctx.subpath)
# prep recursion (only into git-hg subrepos)
if ctx.subrepo and options.recursive and ctx.state[2] == 'hg':
if ctx.subrepo and options.recursive and ctx.state[2] == b'hg':
newctx = self.subcontext(ctx.subrepo)
newctx.level = ctx.level + 1
self.do_operation(options, args, newctx)
def get_git_commit(self, ctx):
src, rev, kind = ctx.state
if kind == 'hg':
if kind == b'hg':
gitcommit = ctx.subrepo.get_git_commit(rev)
if not gitcommit:
die('could not determine git commit for %s; a fetch may update notes' % rev)
die(b'could not determine git commit for %s; a fetch may update notes' % rev)
else:
gitcommit = rev
return gitcommit
@@ -681,28 +806,28 @@ class SubRepoCommand(SubCommand):
if not ctx.subrepo:
return
src, orig, kind = ctx.state
gitcommit = ctx.subrepo.rev_parse('HEAD')
gitcommit = ctx.subrepo.rev_parse(b'HEAD')
if not gitcommit:
die('could not determine current HEAD state in %s' % ctx.subrepo.topdir)
die(b'could not determine current HEAD state in %s' % ctx.subrepo.topdir)
rev = gitcommit
if kind == 'hg':
if kind == b'hg':
rev = ctx.subrepo.get_hg_rev(gitcommit)
if not rev:
die('could not determine hg changeset for commit %s' % gitcommit)
die(b'could not determine hg changeset for commit %s' % gitcommit)
else:
rev = gitcommit
# obtain state from index
state_path = os.path.join(ctx.repo.topdir, '.hgsubstate')
state_path = os.path.join(ctx.repo.topdir, b'.hgsubstate')
# should have this, since we have subrepo (state) in the first place ...
if not os.path.exists(state_path):
die('no .hgsubstate found in repo %s' % ctx.repo.topdir)
die(b'no .hgsubstate found in repo %s' % ctx.repo.topdir)
if orig != rev:
short = ctx.subrepo.rev_parse(['--short', gitcommit])
print "Updating %s to %s [git %s]" % (ctx.subpath, rev, short)
puts(b"Updating %s to %s [git %s]" % (ctx.subpath, rev, short))
# replace and update index
with open(state_path, 'r') as f:
with open(state_path, 'rb') as f:
state = f.read()
state = re.sub('.{40} %s' % (ctx.relpath), '%s %s' % (rev, ctx.relpath), state)
state = re.sub(b'.{40} %s' % (ctx.relpath), b'%s %s' % (rev, ctx.relpath), state)
with open(state_path, 'wb') as f:
f.write(state)
@@ -710,7 +835,7 @@ class SubRepoCommand(SubCommand):
if not ctx.subrepo:
return
if not options.quiet:
print 'Entering %s' % ctx.subpath
puts(b'Entering %s' % ctx.subpath)
sys.stdout.flush()
newenv = os.environ.copy()
newenv['path'] = ctx.relpath
@@ -721,7 +846,7 @@ class SubRepoCommand(SubCommand):
proc = subprocess.Popen(options.command, shell=True, cwd=ctx.subpath, env=newenv)
proc.wait()
if proc.returncode != 0:
die('stopping at %s; script returned non-zero status' % ctx.subpath)
die(b'stopping at %s; script returned non-zero status' % ctx.subpath)
def cmd_update(self, options, args, ctx):
if not ctx.subrepo:
@@ -729,7 +854,7 @@ class SubRepoCommand(SubCommand):
self.run_cmd(options, ctx.repo, ['clone', src, ctx.subpath], cwd=None)
ctx.subrepo = self.git_hg_repo_try(ctx.subpath)
if not ctx.subrepo:
die('subrepo %s setup clone failed', ctx.subpath)
die(b'subrepo %s setup clone failed' % ctx.subpath)
# force (detached) checkout of target commit following clone
cmd = [ 'checkout', '-q' ]
else:
@@ -757,32 +882,32 @@ class SubRepoCommand(SubCommand):
def cmd_status(self, options, args, ctx):
if not ctx.subrepo:
state = '-'
revname = ''
state = b'-'
revname = b''
_, gitcommit, kind = ctx.state
if kind != 'git':
gitcommit += '[hg] '
if kind != b'git':
gitcommit += b'[hg] '
else:
gitcommit = self.get_git_commit(ctx)
head = ctx.subrepo.rev_parse('HEAD')
head = ctx.subrepo.rev_parse(b'HEAD')
if head == gitcommit:
state = ' '
state = b' '
else:
state = '+'
state = b'+'
# option determines what to print
if not options.cached:
gitcommit = head
revname = ctx.subrepo.rev_describe(gitcommit)
if revname:
revname = ' (%s)' % revname
print "%s%s %s%s" % (state, gitcommit, ctx.subpath, revname)
revname = b' (%s)' % revname
puts(b"%s%s %s%s" % (state, gitcommit, ctx.subpath, revname))
def cmd_sync(self, options, args, ctx):
if not ctx.subrepo:
return
src, _, _ = ctx.state
self.run_cmd(options, ctx.subrepo, \
['config', 'remote.%s.url' % (options.remote), src])
['config', b'remote.%s.url' % (options.remote), src])
class RepoCommand(SubCommand):
@@ -801,7 +926,7 @@ class RepoCommand(SubCommand):
(remote, args) = self.get_remote(args)
repos = self.githgrepo.get_hg_repos()
if remote in repos:
print repos[remote].rstrip('/')
puts(repos[remote].rstrip(b'/'))
class HgCommand(SubCommand):
@@ -821,8 +946,8 @@ class HgCommand(SubCommand):
remote = self.subcommand
repos = self.githgrepo.get_hg_repos()
if len(args) and remote in repos:
if args[0].find('hg') < 0:
args.insert(0, 'hg')
if args[0].find(b'hg') < 0:
args.insert(0, b'hg')
args[1:1] = ['-R', repos[remote]]
p = subprocess.Popen(args, stdout=None)
p.wait()
@@ -847,12 +972,13 @@ class HelpCommand(SubCommand):
def get_subcommands():
commands = {
'hg-rev': HgRevCommand,
'git-rev': GitRevCommand,
'repo': RepoCommand,
'gc': GcCommand,
'sub': SubRepoCommand,
'help' : HelpCommand
b'hg-rev': HgRevCommand,
b'git-rev': GitRevCommand,
b'repo': RepoCommand,
b'gc': GcCommand,
b'sub': SubRepoCommand,
b'mapfile': MapFileCommand,
b'help' : HelpCommand
}
# add remote named subcommands
repos = githgrepo.get_hg_repos()
@@ -874,6 +1000,7 @@ def do_usage():
gc \t perform maintenance and consistency cleanup on repo tracking marks
sub \t manage subrepos
repo \t show local hg repo backing a remote
mapfile \t dump a hg-git git-mapfile
If the subcommand is the name of a remote hg repo, then any remaining arguments
are considered a "hg command", e.g. hg heads, or thg, and it is then executed
@@ -885,11 +1012,12 @@ def do_usage():
Available hg remotes:
""")
usage = compat.to_b(usage)
for r in githgrepo.get_hg_repos():
usage += '\t%s\n' % (r)
usage += '\n'
sys.stderr.write(usage)
sys.stderr.flush()
usage += b'\t%s\n' % (r)
usage += b'\n'
compat.stderr.write(usage)
compat.stderr.flush()
sys.exit(2)
def init_git(gitdir=None):
@@ -897,7 +1025,7 @@ def init_git(gitdir=None):
try:
githgrepo = GitHgRepo(gitdir=gitdir)
except Exception, e:
except Exception as e:
die(str(e))
def init_logger():
@@ -916,8 +1044,8 @@ def init_version():
global hg_version
try:
version, _, extra = util.version().partition('+')
version = list(int(e) for e in version.split('.'))
version, _, extra = util.version().partition(b'+')
version = list(int(e) for e in version.split(b'.'))
if extra:
version[-1] += 1
hg_version = tuple(version)
@@ -933,19 +1061,21 @@ def main(argv):
global subcommands
# as an alias, cwd is top dir, change again to original directory
reldir = os.environ.get('GIT_PREFIX')
reldir = compat.getenv(b'GIT_PREFIX', None)
if reldir:
os.chdir(reldir)
# init repo dir
# we will take over dir management ...
init_git(os.environ.pop('GIT_DIR', None))
gitdir = compat.getenv(b'GIT_DIR', None)
os.environ.pop('GIT_DIR', None)
init_git(gitdir)
subcommands = get_subcommands()
cmd = ''
if len(argv) > 1:
cmd = argv[1]
cmd = compat.decode_sysarg(argv[1])
argv = argv[2:]
if cmd in subcommands:
c = subcommands[cmd]

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
)

View File

@@ -1,9 +1,9 @@
RM ?= rm -f
T = main.t main-push.t bidi.t helper.t
TEST_DIRECTORY := $(CURDIR)
SHARNESS_TEST_DIRECTORY := $(CURDIR)
export TEST_DIRECTORY
export SHARNESS_TEST_DIRECTORY
all: test
@@ -11,7 +11,7 @@ test: $(T)
$(MAKE) clean
$(T):
$(SHELL) $@ $(TEST_OPTS)
./$@ $(TEST_OPTS)
clean:
$(RM) -r 'trash directory'.* test-results

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Copyright (c) 2012 Felipe Contreras
#
@@ -8,20 +8,7 @@
test_description='Test bidirectionality of remote-hg'
test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/
. "$TEST_DIRECTORY"/test-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
if ! python2 -c 'import mercurial' > /dev/null 2>&1
then
skip_all='skipping remote-hg tests; mercurial not available'
test_done
fi
. ./test-lib.sh
# clone to a git repo
git_clone () {
@@ -243,4 +230,42 @@ test_expect_success 'hg tags' '
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
'
test_done

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

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

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

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

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

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
test/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

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

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Copyright (c) 2016 Mark Nauwelaerts
#
@@ -8,18 +8,11 @@
test_description='Test git-hg-helper'
test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/
. "$TEST_DIRECTORY"/test-lib.sh
. ./test-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
if ! python2 -c 'import mercurial' > /dev/null 2>&1
then
skip_all='skipping remote-hg tests; mercurial not available'
skip_all='skipping remote-hg tests; python with mercurial not available'
test_done
fi
@@ -106,7 +99,7 @@ test_expect_success 'subcommand repo - with local proxy' '
test_cmp expected actual
'
test_expect_success 'subcommands hg-rev and git-rev' '
test_expect_success 'subcommands hg-rev and git-rev and mapfile' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
setup_repos &&
@@ -117,7 +110,9 @@ test_expect_success 'subcommands hg-rev and git-rev' '
test -s rev-HEAD &&
git-hg-helper hg-rev `cat rev-HEAD` > hg-HEAD &&
git-hg-helper git-rev `cat hg-HEAD` > git-HEAD &&
test_cmp rev-HEAD git-HEAD
git-hg-helper mapfile --output mapfile origin &&
test_cmp rev-HEAD git-HEAD &&
grep "`cat rev-HEAD` `cat hg-HEAD`" mapfile
)
'
@@ -521,8 +516,8 @@ test_expect_success 'subcommand sub status' '
(
cd gitrepo &&
git-hg-helper sub update sub_hg_a --force &&
git-hg-helper sub update sub_git --force &&
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 &&
@@ -544,4 +539,4 @@ test_expect_success 'subcommand sub status' '
)
'
test_done
test_done

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Copyright (c) 2012 Felipe Contreras
#
@@ -6,51 +6,24 @@
# https://bitbucket.org/durin42/hg-git/src
#
# shellcheck disable=SC2016,SC2034,SC2086,SC2164,SC1091
test_description='Test remote-hg output compared to hg-git'
test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/
. "$TEST_DIRECTORY"/test-lib.sh
. ./test-lib.sh
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
export EXPECTED_DIR="$SHARNESS_TEST_DIRECTORY/expected"
if ! python2 -c 'import mercurial' > /dev/null 2>&1
then
skip_all='skipping remote-hg tests; mercurial not available'
test_done
fi
if python2 -c 'import hggit' > /dev/null 2>&1
then
hggit=hggit
elif python2 -c 'import hgext.git' > /dev/null 2>&1
then
hggit=hgext.git
else
skip_all='skipping remote-hg tests; hg-git not available'
test_done
fi
hg_version=$(python2 -c 'from mercurial import util; print util.version()')
case $hg_version in
3.0*+*)
skip_all='skipping remote-hg tests; unsuported version of hg by hg-git'
test_done
;;
esac
# clone to a git repo with git
git_clone_git () {
git_clone () {
git clone -q "hg::$1" $2 &&
(cd $2 && git checkout master && git branch -D default)
(
cd $2 &&
git checkout master &&
{ git branch -D default || true ;}
)
}
# clone to an hg repo with git
hg_clone_git () {
hg_clone () {
(
hg init $2 &&
hg -R $2 bookmark -i master &&
@@ -61,80 +34,112 @@ hg_clone_git () {
(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 () {
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
)
}
# push an hg git repo with hg
hg_push_hg () {
(
cd $1 &&
hg -q push ../$2 || true
git checkout -q '@{-1}' &&
{ git branch -q -D tmp 2> /dev/null || true ;}
)
}
hg_log () {
hg -R $1 log --graph --debug > log &&
grep -v 'tag: *default/' 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 --git-dir=$1/.git fast-export --branches
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 &&
cat > "$HOME"/.hgrc <<-EOF
[ui]
username = A U Thor <author@example.com>
[defaults]
backout = -d "0 0"
commit = -d "0 0"
debugrawcommit = -d "0 0"
tag = -d "0 0"
[extensions]
$hggit =
graphlog =
EOF
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
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
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
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
test_expect_success 'executable bit' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
# 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 &&
@@ -150,27 +155,10 @@ test_expect_success 'executable bit' '
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
cmp_hg_to_git_manifest "hg manifest -v -r -1; hg manifest -v"
'
test_expect_success 'symlink' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
test_expect_success !WIN 'symlink' '
(
git init -q gitrepo &&
cd gitrepo &&
@@ -182,26 +170,10 @@ test_expect_success 'symlink' '
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
cmp_hg_to_git_manifest "hg manifest -v"
'
test_expect_success 'merge conflict 1' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
hg init hgrepo1 &&
cd hgrepo1 &&
@@ -210,33 +182,22 @@ test_expect_success 'merge conflict 1' '
hg ci -m "origin" &&
echo B > afile &&
hg ci -m "A->B" &&
hg ci -m "A->B" -d "1 0" &&
hg up -r0 &&
echo C > afile &&
hg ci -m "A->C" &&
hg ci -m "A->C" -d "2 0" &&
hg merge -r1 &&
echo C > afile &&
hg resolve -m afile &&
hg ci -m "merge to C"
hg ci -m "merge to C" -d "3 0"
) &&
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
cmp_hg_to_git_log_hgrepo1
'
test_expect_success 'merge conflict 2' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
hg init hgrepo1 &&
cd hgrepo1 &&
@@ -245,33 +206,22 @@ test_expect_success 'merge conflict 2' '
hg ci -m "origin" &&
echo B > afile &&
hg ci -m "A->B" &&
hg ci -m "A->B" -d "1 0" &&
hg up -r0 &&
echo C > afile &&
hg ci -m "A->C" &&
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"
hg ci -m "merge to B" -d "3 0"
) &&
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
cmp_hg_to_git_log_hgrepo1
'
test_expect_success 'converged merge' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
hg init hgrepo1 &&
cd hgrepo1 &&
@@ -280,34 +230,23 @@ test_expect_success 'converged merge' '
hg ci -m "origin" &&
echo B > afile &&
hg ci -m "A->B" &&
hg ci -m "A->B" -d "1 0" &&
echo C > afile &&
hg ci -m "B->C" &&
hg ci -m "B->C" -d "2 0" &&
hg up -r0 &&
echo C > afile &&
hg ci -m "A->C" &&
hg ci -m "A->C" -d "3 0" &&
hg merge -r2 || true &&
hg ci -m "merge"
hg ci -m "merge" -d "4 0"
) &&
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
cmp_hg_to_git_log_hgrepo1
'
test_expect_success 'encoding' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
@@ -332,22 +271,17 @@ test_expect_success 'encoding' '
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 &&
hg_clone gitrepo hgrepo &&
git_clone hgrepo gitrepo2 &&
HGENCODING=utf-8 hg_log hgrepo-$x > "hg-log-$x" &&
git_log gitrepo2-$x > "git-log-$x"
done &&
HGENCODING=utf-8 hg_log hgrepo > hg-log &&
git_log gitrepo2 > git-log &&
test_cmp hg-log-hg hg-log-git &&
test_cmp git-log-hg git-log-git
test_cmp_expected hg-log &&
test_cmp_expected git-log
'
test_expect_success 'file removal' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
@@ -367,27 +301,10 @@ test_expect_success 'file removal' '
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
cmp_hg_to_git_manifest "hg manifest -r 3; hg manifest"
'
test_expect_success 'git tags' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
@@ -403,153 +320,127 @@ test_expect_success 'git tags' '
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 &&
hg_clone gitrepo hgrepo &&
hg_log hgrepo > log &&
test_cmp log-hg log-git
test_cmp_expected log
'
test_expect_success 'hg author' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
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
) &&
echo alpha > alpha &&
git add alpha &&
git commit -m "add alpha" &&
git checkout -q -b not-master
) &&
(
hg_clone gitrepo hgrepo &&
cd hgrepo &&
(
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" &&
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 >> 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 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 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 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 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 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 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"
) &&
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 &&
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
cmp_hg_to_git_log
'
test_expect_success 'hg branch' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
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
) &&
echo alpha > alpha &&
git add alpha &&
git commit -q -m "add alpha" &&
git checkout -q -b not-master
) &&
(
hg_clone gitrepo hgrepo &&
(
hg_clone_$x gitrepo-$x hgrepo-$x &&
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"
) &&
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 hgrepo gitrepo &&
hg_clone gitrepo hgrepo2 &&
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
cmp_hg_to_git_log
'
test_expect_success 'hg tags' '
test_when_finished "rm -rf gitrepo* hgrepo*" &&
(
git init -q gitrepo &&
cd gitrepo &&
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
) &&
echo alpha > alpha &&
git add alpha &&
git commit -m "add alpha" &&
git checkout -q -b not-master
) &&
(
hg_clone gitrepo hgrepo &&
(
hg_clone_$x gitrepo-$x hgrepo-$x &&
cd hgrepo &&
hg co master &&
hg tag alpha
) &&
cd hgrepo-$x &&
hg co master &&
hg tag alpha
) &&
hg_push hgrepo gitrepo &&
hg_clone gitrepo hgrepo2 &&
hg_push_$x hgrepo-$x gitrepo-$x &&
hg_clone_$x gitrepo-$x hgrepo2-$x &&
(
git -C gitrepo tag -l &&
hg_log hgrepo2 &&
cat hgrepo2/.hgtags
) > output &&
(
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_cmp_expected output
'
test_done

View File

@@ -1,7 +1,8 @@
#!/bin/bash
CAPABILITY_PUSH=t
test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/
. "$TEST_DIRECTORY"/main.t
. ./main.t
# .. and some push mode only specific tests
@@ -270,10 +271,10 @@ test_expect_success 'push with renamed executable preserves executable bit' '
) &&
(
umask 0 &&
cd hgrepo &&
hg update &&
stat content2 >expected &&
# umask mileage might vary
grep -- -r.xr.xr.x expected
)
'

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Copyright (c) 2012 Felipe Contreras
#
@@ -8,8 +8,7 @@
test_description='Test remote-hg'
test -n "$TEST_DIRECTORY" || TEST_DIRECTORY=$(dirname $0)/
. "$TEST_DIRECTORY"/test-lib.sh
. ./test-lib.sh
if test "$CAPABILITY_PUSH" = "t"
then
@@ -20,18 +19,6 @@ else
git config --global remote-hg.capability-push false
fi
if ! test_have_prereq PYTHON
then
skip_all='skipping remote-hg tests; python not available'
test_done
fi
if ! python2 -c 'import mercurial' > /dev/null 2>&1
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 &&
@@ -96,14 +83,14 @@ check_push () {
'')
grep "^ [a-f0-9]*\.\.[a-f0-9]* *${branch} -> ${branch}$" error || ref_ret=1
;;
*)
echo "BUG: wrong kind '$kind'" && return 3
;;
esac
test $ref_ret -ne 0 && echo "match for '$branch' failed" && break
test $ref_ret -ne 0 && echo "match for '$branch' failed" && return 2
done
if test $expected_ret -ne $ret || test $ref_ret -ne 0
then
return 1
fi
test $expected_ret -ne $ret && return 1
return 0
}
@@ -281,6 +268,41 @@ test_expect_success 'strip' '
test_cmp actual expected
'
test_expect_success 'dotfiles' '
test_when_finished "rm -rf hgrepo gitrepo" &&
(
hg init hgrepo &&
cd hgrepo &&
echo one >.git &&
echo ONE >.GIT &&
mkdir a && echo two > a/.gitmodules &&
hg add .git .GIT a/.gitmodules &&
hg commit -m zero
) &&
git clone "hg::hgrepo" gitrepo &&
test_cmp gitrepo/.git_ hgrepo/.git &&
test_cmp gitrepo/.GIT_ hgrepo/.GIT &&
test_cmp gitrepo/a/.gitmodules_ hgrepo/a/.gitmodules &&
(
cd gitrepo &&
echo three >.git_ &&
echo THREE >.GIT &&
echo four >a/.gitmodules_ &&
git add .git_ .GIT_ a/.gitmodules_ &&
git commit -m one &&
git push
) &&
hg -R hgrepo update &&
test_cmp gitrepo/.git_ hgrepo/.git &&
test_cmp gitrepo/.GIT_ hgrepo/.GIT &&
test_cmp gitrepo/a/.gitmodules_ hgrepo/a/.gitmodules
'
test_expect_success 'remote push with master bookmark' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
@@ -519,7 +541,7 @@ else
test_expect_failure "$testcopyrenamedesc" "$testcopyrename"
fi
test_expect_success 'fetch special filenames' '
test_expect_success !WIN 'fetch special filenames' '
test_when_finished "rm -rf hgrepo gitrepo && LC_ALL=C" &&
LC_ALL=en_US.UTF-8
@@ -658,16 +680,27 @@ test_expect_success 'remote big push' '
(
cd gitrepo &&
check_push 1 --all <<-\EOF
master
good_bmark
branches/good_branch
new_bmark:new
branches/new_branch:new
bad_bmark1:non-fast-forward
bad_bmark2:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
if test "$CAPABILITY_PUSH" = "t"
then
# cap push handles refs one by one
# so it will still correctly report several ok
check_push 1 --all <<-\EOF
master
good_bmark
branches/good_branch
new_bmark:new
branches/new_branch:new
bad_bmark1:non-fast-forward
bad_bmark2:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
else
check_push 1 --all <<-\EOF
bad_bmark1:non-fast-forward
bad_bmark2:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
fi
) &&
if test "$CAPABILITY_PUSH" = "t"
@@ -681,16 +714,18 @@ test_expect_success 'remote big push' '
check_bookmark hgrepo good_bmark three &&
check_bookmark hgrepo bad_bmark1 one &&
check_bookmark hgrepo bad_bmark2 one &&
check_bookmark hgrepo new_bmark six
check_bookmark hgrepo new_bmark six &&
check gitrepo origin/master two
else
check_branch hgrepo default one &&
check_branch hgrepo good_branch "good branch" &&
check_branch hgrepo bad_branch "bad branch" &&
check_branch hgrepo new_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 ''
check_bookmark hgrepo new_bmark &&
check gitrepo origin/master one
fi
'
@@ -740,12 +775,21 @@ test_expect_success 'remote big push non fast forward' '
echo five > content &&
git commit -q -a -m five &&
check_push 1 --all <<-\EOF &&
master
good_bmark
bad_bmark:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
if test "$CAPABILITY_PUSH" = "t"
then
check_push 1 --all <<-\EOF
master
good_bmark
bad_bmark:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
else
# cap export now only report error cases
check_push 1 --all <<-\EOF
bad_bmark:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
fi &&
git fetch &&
@@ -755,14 +799,12 @@ test_expect_success 'remote big push non fast forward' '
# so it will already have pushed some above previously
# (and master is a fake one that jumps around a bit)
check_push 1 --all <<-\EOF
master:non-fast-forward
bad_bmark:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
else
# cap export now only report error cases
check_push 1 --all <<-\EOF
master
good_bmark
bad_bmark:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
@@ -770,7 +812,7 @@ test_expect_success 'remote big push non fast forward' '
)
'
test_expect_failure 'remote big push force' '
test_expect_success 'remote big push force' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_big_push
@@ -778,19 +820,33 @@ test_expect_failure 'remote big push force' '
(
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
if test "$CAPABILITY_PUSH" = "t"
then
check_push 0 --force --all <<-\EOF
master:forced-update
good_bmark:forced-update
branches/good_branch:forced-update
new_bmark:new
branches/new_branch:new
bad_bmark1:forced-update
bad_bmark2:forced-update
branches/bad_branch:forced-update
EOF
else
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
fi
) &&
check_branch hgrepo default six &&
check gitrepo origin/master two &&
check_branch hgrepo good_branch eight &&
check_branch hgrepo bad_branch nine &&
check_branch hgrepo new_branch ten &&
@@ -808,16 +864,27 @@ test_expect_success 'remote big push dry-run' '
(
cd gitrepo &&
check_push 1 --dry-run --all <<-\EOF &&
master
good_bmark
branches/good_branch
new_bmark:new
branches/new_branch:new
bad_bmark1:non-fast-forward
bad_bmark2:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
if test "$CAPABILITY_PUSH" = "t"
then
# cap push handles refs one by one
# so it will still correctly report several ok
check_push 1 --dry-run --all <<-\EOF
master
good_bmark
branches/good_branch
new_bmark:new
branches/new_branch:new
bad_bmark1:non-fast-forward
bad_bmark2:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
else
check_push 1 --dry-run --all <<-\EOF
bad_bmark1:non-fast-forward
bad_bmark2:non-fast-forward
branches/bad_branch:non-fast-forward
EOF
fi &&
check_push 0 --dry-run master good_bmark new_bmark branches/good_branch branches/new_branch <<-\EOF
master
@@ -828,14 +895,60 @@ test_expect_success 'remote big push dry-run' '
EOF
) &&
check gitrepo origin/master one &&
check_branch hgrepo default one &&
check_branch hgrepo good_branch "good branch" &&
check_branch hgrepo bad_branch "bad branch" &&
check_branch hgrepo new_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 ''
check_bookmark hgrepo new_bmark
'
test_expect_success 'remote big push force dry-run' '
test_when_finished "rm -rf hgrepo gitrepo*" &&
setup_big_push
(
cd gitrepo &&
if test "$CAPABILITY_PUSH" = "t"
then
check_push 0 --force --dry-run --all <<-\EOF
master:forced-update
good_bmark:forced-update
branches/good_branch:forced-update
new_bmark:new
branches/new_branch:new
bad_bmark1:forced-update
bad_bmark2:forced-update
branches/bad_branch:forced-update
EOF
else
check_push 0 --force --dry-run --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
fi
) &&
check gitrepo origin/master one &&
check_branch hgrepo default one &&
check_branch hgrepo good_branch "good branch" &&
check_branch hgrepo bad_branch "bad branch" &&
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' '
@@ -995,7 +1108,7 @@ testpushupdatesnotes='
(
cd gitrepo &&
echo two > content &&
git commit -a -m two
git commit -a -m two &&
git push
) &&
@@ -1081,7 +1194,7 @@ test_expect_success 'push merged named branch' '
git push
) &&
cat > expected <<-EOF
cat > expected <<-EOF &&
Merge
three
two
@@ -1122,7 +1235,7 @@ test_expect_success 'push tag different branch' '
cd hgrepo &&
echo one > content &&
hg add content &&
hg commit -m one
hg commit -m one &&
hg branch feature &&
echo two > content &&
hg commit -m two
@@ -1229,6 +1342,55 @@ test_expect_success 'clone can ignore invalid refnames' '
check_files gitrepo "test.txt"
'
test_expect_success 'push annotated tag' '
test_when_finished "rm -rf hgrepo gitrepo" &&
(
hg init hgrepo &&
cd hgrepo &&
echo one > content &&
hg add content &&
hg commit -m one
) &&
(
git clone "hg::hgrepo" gitrepo &&
cd gitrepo &&
git tag -m "Version 1.0" v1.0 &&
git push --tags
) &&
cat > expected <<-\EOF &&
tip:Version 1.0:C O Mitter <committer@example.com>
v1.0:one:H G Wells <wells@example.com>
EOF
hg -R hgrepo log --template "{tags}:{desc}:{author}\n" > actual &&
test_cmp expected actual
'
test_expect_success 'timezone issues with negative offsets' '
test_when_finished "rm -rf hgrepo gitrepo1 gitrepo2" &&
hg init hgrepo &&
(
git clone "hg::hgrepo" gitrepo1 &&
cd gitrepo1 &&
echo two >> content &&
git add content &&
git commit -m two --date="2016-09-26 00:00:00 -0230" &&
git push
) &&
git clone "hg::hgrepo" gitrepo2 &&
git --git-dir=gitrepo1/.git log -1 --format="%ai" > expected &&
git --git-dir=gitrepo2/.git log -1 --format="%ai" > actual &&
test_cmp expected actual
'
if test "$CAPABILITY_PUSH" != "t"
then
test_done

View File

@@ -18,33 +18,80 @@
# along with this program. If not, see http://www.gnu.org/licenses/ .
# Public: Current version of Sharness.
SHARNESS_VERSION="0.3.0"
SHARNESS_VERSION="1.1.0"
export SHARNESS_VERSION
# Public: The file extension for tests. By default, it is set to "t".
: ${SHARNESS_TEST_EXTENSION:=t}
: "${SHARNESS_TEST_EXTENSION:=t}"
export SHARNESS_TEST_EXTENSION
# Keep the original TERM for say_color
ORIGINAL_TERM=$TERM
# Public: Root directory containing tests. Tests can override this variable,
# e.g. for testing Sharness itself.
if test -z "$SHARNESS_TEST_DIRECTORY"
then
SHARNESS_TEST_DIRECTORY=$(pwd)
else
# ensure that SHARNESS_TEST_DIRECTORY is an absolute path so that it
# is valid even if the current working directory is changed
SHARNESS_TEST_DIRECTORY=$(cd "$SHARNESS_TEST_DIRECTORY" && pwd) || exit 1
fi
export SHARNESS_TEST_DIRECTORY
if test -z "$SHARNESS_TEST_OUTPUT_DIRECTORY"
then
# Similarly, override this to store the test-results subdir
# elsewhere
SHARNESS_TEST_OUTPUT_DIRECTORY=$SHARNESS_TEST_DIRECTORY
fi
# Reset TERM to original terminal if found, otherwise save original TERM
[ "x" = "x$SHARNESS_ORIG_TERM" ] &&
SHARNESS_ORIG_TERM="$TERM" ||
TERM="$SHARNESS_ORIG_TERM"
# Public: The unsanitized TERM under which sharness is originally run
export SHARNESS_ORIG_TERM
# Export SHELL_PATH
: "${SHELL_PATH:=$SHELL}"
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_OUTPUT_DIRECTORY/test-results"
BASE="$SHARNESS_TEST_OUTPUT_DIRECTORY/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
PAGER="cat"
TZ=UTC
TERM=dumb
EDITOR=:
export LANG LC_ALL PAGER TZ TERM EDITOR
export LANG LC_ALL PAGER TZ EDITOR
unset VISUAL CDPATH GREP_OPTIONS
# Line feed
LF='
'
[ "x$ORIGINAL_TERM" != "xdumb" ] && (
TERM=$ORIGINAL_TERM &&
export TERM &&
[ "x$TERM" != "xdumb" ] && (
[ -t 1 ] &&
tput bold >/dev/null 2>&1 &&
tput setaf 1 >/dev/null 2>&1 &&
@@ -60,6 +107,8 @@ while test "$#" -ne 0; do
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)
@@ -68,49 +117,69 @@ while test "$#" -ne 0; do
# 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 ;;
--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() {
(
TERM=$ORIGINAL_TERM
export TERM
test -z "$1" && test -n "$quiet" && return
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;;
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" "$*"
tput sgr0
echo
)
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" "$*"
printf '%s\n' "$*"
}
fi
TERM=dumb
export TERM
error() {
say_color error "error: $*"
EXIT_OK=t
@@ -121,7 +190,7 @@ say() {
say_color info "$*"
}
test -n "$test_description" || error "Test script did not set test_description."
test -n "${test_description:-}" || error "Test script did not set test_description."
if test "$help" = "t"; then
echo "$test_description"
@@ -130,7 +199,11 @@ fi
exec 5>&1
exec 6<&0
if test "$verbose" = "t"; then
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
@@ -161,7 +234,7 @@ trap 'die' EXIT
# 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)
# $1 - Name of prerequisite (a simple word, in all capital letters by convention)
#
# Examples
#
@@ -198,7 +271,7 @@ test_have_prereq() {
# prerequisites can be concatenated with ','
save_IFS=$IFS
IFS=,
set -- $*
set -- $@
IFS=$save_IFS
total_prereq=0
@@ -215,7 +288,7 @@ test_have_prereq() {
negative_prereq=
esac
total_prereq=$(($total_prereq + 1))
total_prereq=$((total_prereq + 1))
case "$satisfied_prereq" in
*" $prerequisite "*)
satisfied_this_prereq=t
@@ -226,7 +299,7 @@ test_have_prereq() {
case "$satisfied_this_prereq,$negative_prereq" in
t,|,t)
ok_prereq=$(($ok_prereq + 1))
ok_prereq=$((ok_prereq + 1))
;;
*)
# Keep a list of missing prerequisites; restore
@@ -247,12 +320,12 @@ test_have_prereq() {
# the text_expect_* functions instead.
test_ok_() {
test_success=$(($test_success + 1))
say_color "" "ok $test_count - $@"
test_success=$((test_success + 1))
say_color "" "ok $test_count - $*"
}
test_failure_() {
test_failure=$(($test_failure + 1))
test_failure=$((test_failure + 1))
say_color error "not ok $test_count - $1"
shift
echo "$@" | sed -e 's/^/# /'
@@ -260,13 +333,13 @@ test_failure_() {
}
test_known_broken_ok_() {
test_fixed=$(($test_fixed + 1))
say_color error "ok $test_count - $@ # TODO known breakage vanished"
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"
test_broken=$((test_broken + 1))
say_color warn "not ok $test_count - $* # TODO known breakage"
}
# Public: Execute commands in debug mode.
@@ -287,10 +360,29 @@ test_debug() {
test "$debug" = "" || eval "$1"
}
# Public: Stop execution and start a shell.
#
# This is useful for debugging tests and only makes sense together with "-v".
# Be sure to remove all invocations of this command before submitting.
test_pause() {
if test "$verbose" = t; then
"$SHELL_PATH" <&6 >&3 2>&4
else
error >&5 "test_pause requires --verbose"
fi
}
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 "$*"
case ",$test_prereq," in
*,INTERACTIVE,*)
eval "$*"
;;
*)
eval </dev/null >&3 2>&4 "$*"
;;
esac
}
test_run_() {
@@ -299,6 +391,13 @@ test_run_() {
test_eval_ "$1"
eval_ret=$?
if test "$chain_lint" = "t"; then
test_eval_ "(exit 117) && $1"
if test "$?" != 117; then
error "bug in the test script: broken &&-chain: $1"
fi
fi
if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"; then
test_eval_ "$test_cleanup"
fi
@@ -309,7 +408,7 @@ test_run_() {
}
test_skip_() {
test_count=$(($test_count + 1))
test_count=$((test_count + 1))
to_skip=
for skp in $SKIP_TESTS; do
case $this_test.$test_count in
@@ -328,7 +427,7 @@ test_skip_() {
of_prereq=" of $test_prereq"
fi
say_color skip >&3 "skipping test: $@"
say_color skip >&3 "skipping test: $*"
say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
: true
;;
@@ -426,6 +525,44 @@ test_expect_failure() {
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: Run command and ensure that it fails in a controlled way.
#
# Use it instead of "! <command>". For example, when <command> dies due to a
@@ -518,7 +655,7 @@ test_expect_code() {
shift
"$@"
exit_code=$?
if test $exit_code = $want_code; then
if test "$exit_code" = "$want_code"; then
return 0
fi
@@ -528,7 +665,7 @@ test_expect_code() {
# Public: Compare two files to see if expected output matches actual output.
#
# The TEST_CMP variable defines the command used for the comparision; it
# The TEST_CMP variable defines the command used for the comparison; it
# defaults to "diff -u". Only when the test script was started with --verbose,
# will the command's output, the diff, be printed to the standard output.
#
@@ -551,6 +688,79 @@ test_cmp() {
${TEST_CMP:-diff -u} "$@"
}
# Public: portably print a sequence of numbers.
#
# seq is not in POSIX and GNU seq might not be available everywhere,
# so it is nice to have a seq implementation, even a very simple one.
#
# $1 - Starting number.
# $2 - Ending number.
#
# Examples
#
# test_expect_success 'foo works 10 times' '
# for i in $(test_seq 1 10)
# do
# foo || return
# done
# '
#
# Returns 0 if all the specified numbers can be displayed.
test_seq() {
i="$1"
j="$2"
while test "$i" -le "$j"
do
echo "$i" || return
i=$(("$i" + 1))
done
}
# Public: Check if the file expected to be empty is indeed empty, and barfs
# otherwise.
#
# $1 - File to check for emptiness.
#
# Returns 0 if file is empty, 1 otherwise.
test_must_be_empty() {
if test -s "$1"
then
echo "'$1' is not empty, it contains:"
cat "$1"
return 1
fi
}
# debugging-friendly alternatives to "test [-f|-d|-e]"
# The commands test the existence or non-existence of $1. $2 can be
# given to provide a more precise diagnosis.
test_path_is_file () {
if ! test -f "$1"
then
echo "File $1 doesn't exist. $2"
false
fi
}
test_path_is_dir () {
if ! test -d "$1"
then
echo "Directory $1 doesn't exist. $2"
false
fi
}
# Check if the directory exists and is empty as expected, barf otherwise.
test_dir_is_empty () {
test_path_is_dir "$1" &&
if test -n "$(find "$1" -mindepth 1 -maxdepth 1)"
then
echo "Directory '$1' is not empty, it contains:"
ls -la "$1"
return 1
fi
}
# Public: Schedule cleanup commands to be run unconditionally at the end of a
# test.
#
@@ -576,6 +786,23 @@ test_when_finished() {
} && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
}
# Public: Schedule cleanup commands to be run unconditionally when all tests
# have run.
#
# This can be used to clean up things like test databases. It is not needed to
# clean up temporary files, as test_done already does that.
#
# Examples:
#
# cleanup mysql -e "DROP DATABASE mytest"
#
# Returns the exit code of the last cleanup command executed.
final_cleanup=
cleanup() {
final_cleanup="{ $*
} && (exit \"\$eval_ret\"); eval_ret=\$?; $final_cleanup"
}
# Public: Summarize test results and exit with an appropriate error code.
#
# Must be called at the end of each test script.
@@ -600,9 +827,9 @@ test_done() {
EXIT_OK=t
if test -z "$HARNESS_ACTIVE"; then
test_results_dir="$SHARNESS_TEST_DIRECTORY/test-results"
test_results_dir="$SHARNESS_TEST_OUTPUT_DIRECTORY/test-results"
mkdir -p "$test_results_dir"
test_results_path="$test_results_dir/${SHARNESS_TEST_FILE%.$SHARNESS_TEST_EXTENSION}.$$.counts"
test_results_path="$test_results_dir/$this_test.$$.counts"
cat >>"$test_results_path" <<-EOF
total $test_count
@@ -621,7 +848,7 @@ test_done() {
say_color warn "# still have $test_broken known breakage(s)"
fi
if test "$test_broken" != 0 || test "$test_fixed" != 0; then
test_remaining=$(( $test_count - $test_broken - $test_fixed ))
test_remaining=$((test_count - test_broken - test_fixed))
msg="remaining $test_remaining test(s)"
else
test_remaining=$test_count
@@ -641,6 +868,8 @@ test_done() {
fi
say "1..$test_count$skip_all"
test_eval_ "$final_cleanup"
test -d "$remove_trash" &&
cd "$(dirname "$remove_trash")" &&
rm -rf "$(basename "$remove_trash")"
@@ -656,14 +885,15 @@ test_done() {
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: Source directory of test code and sharness library.
# This directory may be different from the directory in which tests are
# being run.
: "${SHARNESS_TEST_SRCDIR:=$(cd "$(dirname "$0")" && pwd)}"
export SHARNESS_TEST_SRCDIR
# 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/.."}
: "${SHARNESS_BUILD_DIRECTORY:="$SHARNESS_TEST_DIRECTORY/.."}"
PATH="$SHARNESS_BUILD_DIRECTORY:$PATH"
export PATH SHARNESS_BUILD_DIRECTORY
@@ -672,19 +902,43 @@ 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" ;;
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_OUTPUT_DIRECTORY/$SHARNESS_TRASH_DIRECTORY" ;;
esac
test "$debug" = "t" || remove_trash="$SHARNESS_TRASH_DIRECTORY"
rm -rf "$test_dir" || {
rm -rf "$SHARNESS_TRASH_DIRECTORY" || {
EXIT_OK=t
echo >&5 "FATAL: Cannot prepare test area"
exit 1
}
#
# Load any extensions in $srcdir/sharness.d/*.sh
#
if test -d "${SHARNESS_TEST_SRCDIR}/sharness.d"
then
for file in "${SHARNESS_TEST_SRCDIR}"/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
. "${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
@@ -692,10 +946,10 @@ export SHARNESS_TRASH_DIRECTORY
HOME="$SHARNESS_TRASH_DIRECTORY"
export HOME
mkdir -p "$test_dir" || exit 1
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 "$test_dir" || exit 1
cd -P "$SHARNESS_TRASH_DIRECTORY" || exit 1
this_test=${SHARNESS_TEST_FILE##*/}
this_test=${this_test%.$SHARNESS_TEST_EXTENSION}
@@ -708,4 +962,10 @@ for skp in $SKIP_TESTS; do
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 :

View File

@@ -1,8 +1,62 @@
#!/bin/sh
#!/bin/bash
. ./sharness.sh
: "${SHARNESS_TEST_SRCDIR:=$(cd "$(dirname "${BASH_SOURCE-$0}")" && pwd)}"
test_set_prereq PYTHON
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"
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
GIT_AUTHOR_EMAIL=author@example.com
GIT_AUTHOR_NAME='A U Thor'
@@ -10,3 +64,15 @@ 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
if [[ $(uname -s) = MSYS* ]]; then
test_set_prereq WIN
export TEST_CMP='diff --strip-trailing-cr -u'
fi

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()

46
tools/versions.txt Normal file
View File

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