Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
hg-git
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
mercurial
hg-git
Commits
06366111
Commit
06366111
authored
16 years ago
by
Scott Chacon
Browse files
Options
Downloads
Patches
Plain Diff
initial import of the hg-git bridging extension for mercurial
parents
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
__init__.py
+125
-0
125 additions, 0 deletions
__init__.py
git.py
+146
-0
146 additions, 0 deletions
git.py
with
271 additions
and
0 deletions
__init__.py
0 → 100644
+
125
−
0
View file @
06366111
# 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.
'''
#
# Stage One - use Git commands to do the import / pushes, all in one big uggo file
#
# Stage Two - implement the Git packfile generation and server communication
# in native Python, so we don't need Git locally and don't need
# to keep all the git repo data around. We should just need a SHA
# mapping - since everything is append only in both systems it should
# be pretty simple to do.
#
# just importing every damn thing because i don't know python that well
# and I have no idea what I actually need
from
mercurial
import
util
,
repair
,
merge
,
cmdutil
,
commands
,
error
,
hg
,
url
from
mercurial
import
extensions
,
ancestor
from
mercurial.commands
import
templateopts
from
mercurial.node
import
nullrev
,
nullid
,
short
from
mercurial.i18n
import
_
import
os
,
errno
import
subprocess
def
gclone
(
ui
,
git_url
,
hg_repo_path
=
None
):
## TODO : add git_url as the default remote path
if
not
hg_repo_path
:
hg_repo_path
=
hg
.
defaultdest
(
git_url
)
if
hg_repo_path
.
endswith
(
'
.git
'
):
hg_repo_path
=
hg_repo_path
[:
-
4
]
hg_repo_path
+=
'
-hg
'
subprocess
.
call
([
'
hg
'
,
'
init
'
,
hg_repo_path
])
clone_git
(
git_url
,
git_path
(
hg_repo_path
))
import_git_heads
(
hg_repo_path
)
def
gpull
(
ui
,
repo
,
source
=
'
default
'
,
**
opts
):
"""
fetch from a git repo
"""
lock
=
wlock
=
None
try
:
lock
=
repo
.
lock
()
wlock
=
repo
.
wlock
()
ui
.
write
(
"
fetching from the remote
\n
"
)
git_fetch
()
import_git_heads
()
# do the pull
finally
:
del
lock
,
wlock
def
gpush
(
ui
,
repo
,
dest
=
'
default
'
,
**
opts
):
"""
push to a git repo
"""
lock
=
wlock
=
None
try
:
lock
=
repo
.
lock
()
wlock
=
repo
.
wlock
()
ui
.
write
(
"
pushing to the remote
\n
"
)
# do the push
finally
:
del
lock
,
wlock
def
git_path
(
hg_path
=
None
):
return
os
.
path
.
join
(
hg_path
,
'
.hg
'
,
'
git-remote
'
)
def
clone_git
(
git_url
,
hg_path
=
None
):
git_initialize
(
git_path
(
hg_path
),
git_url
)
git_fetch
(
git_path
(
hg_path
))
def
git_initialize
(
git_path
,
git_url
):
# TODO: implement this in pure python - should be strait-forward
subprocess
.
call
([
'
git
'
,
'
--bare
'
,
'
init
'
,
git_path
])
oldwd
=
os
.
getcwd
()
os
.
chdir
(
git_path
)
subprocess
.
call
([
'
git
'
,
'
remote
'
,
'
add
'
,
'
origin
'
,
git_url
])
os
.
chdir
(
oldwd
)
def
git_fetch
(
git_path
,
remote
=
'
origin
'
):
# TODO: implement this in pure python
# - we'll have to handle ssh and git
oldwd
=
os
.
getcwd
()
os
.
chdir
(
git_path
)
subprocess
.
call
([
'
git
'
,
'
fetch
'
,
remote
])
os
.
chdir
(
oldwd
)
def
git_push
():
# find all the local changesets that aren't mapped
# create git commit object shas and map them
# stick those objects in a packfile and push them up (over ssh)
def
import_git_heads
(
hg_path
=
None
):
# go through each branch
# add all commits we don't have locally
# write a SHA<->SHA mapping table
# update the local branches to match
return
subprocess
.
call
([
'
hg
'
,
'
convert
'
,
git_path
(
hg_path
),
hg_path
])
commands
.
norepo
+=
"
gclone
"
cmdtable
=
{
"
gclone
"
:
(
gclone
,
[
#('A', 'authors', '', 'username mapping filename'),
],
'
Clone a git repository into an hg repository.
'
,
),
"
gpush
"
:
(
gpush
,
[(
'
m
'
,
'
merge
'
,
None
,
_
(
'
merge automatically
'
))],
_
(
'
hg gpush remote
'
)),
"
gpull
"
:
(
gpull
,
[],
_
(
'
hg gpull [--merge] remote
'
)),
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
git.py
0 → 100644
+
146
−
0
View file @
06366111
# git support for the convert extension
import
os
from
mercurial
import
util
from
common
import
NoRepo
,
commit
,
converter_source
,
checktool
class
git_tool
:
# Windows does not support GIT_DIR= construct while other systems
# cannot remove environment variable. Just assume none have
# both issues.
if
hasattr
(
os
,
'
unsetenv
'
):
def
gitcmd
(
self
,
s
):
prevgitdir
=
os
.
environ
.
get
(
'
GIT_DIR
'
)
os
.
environ
[
'
GIT_DIR
'
]
=
self
.
path
try
:
return
util
.
popen
(
s
,
'
rb
'
)
finally
:
if
prevgitdir
is
None
:
del
os
.
environ
[
'
GIT_DIR
'
]
else
:
os
.
environ
[
'
GIT_DIR
'
]
=
prevgitdir
else
:
def
gitcmd
(
self
,
s
):
return
util
.
popen
(
'
GIT_DIR=%s %s
'
%
(
self
.
path
,
s
),
'
rb
'
)
def
__init__
(
self
,
ui
,
path
,
rev
=
None
):
super
(
convert_git
,
self
).
__init__
(
ui
,
path
,
rev
=
rev
)
if
os
.
path
.
isdir
(
path
+
"
/.git
"
):
path
+=
"
/.git
"
if
not
os
.
path
.
exists
(
path
+
"
/objects
"
):
raise
NoRepo
(
"
%s does not look like a Git repo
"
%
path
)
checktool
(
'
git
'
,
'
git
'
)
self
.
path
=
path
def
getheads
(
self
):
if
not
self
.
rev
:
return
self
.
gitcmd
(
'
git rev-parse --branches --remotes
'
).
read
().
splitlines
()
else
:
fh
=
self
.
gitcmd
(
"
git rev-parse --verify %s
"
%
self
.
rev
)
return
[
fh
.
read
()[:
-
1
]]
def
catfile
(
self
,
rev
,
type
):
if
rev
==
"
0
"
*
40
:
raise
IOError
()
fh
=
self
.
gitcmd
(
"
git cat-file %s %s
"
%
(
type
,
rev
))
return
fh
.
read
()
def
getfile
(
self
,
name
,
rev
):
return
self
.
catfile
(
rev
,
"
blob
"
)
def
getmode
(
self
,
name
,
rev
):
return
self
.
modecache
[(
name
,
rev
)]
def
getchanges
(
self
,
version
):
self
.
modecache
=
{}
fh
=
self
.
gitcmd
(
"
git diff-tree -z --root -m -r %s
"
%
version
)
changes
=
[]
seen
=
{}
entry
=
None
for
l
in
fh
.
read
().
split
(
'
\x00
'
):
if
not
entry
:
if
not
l
.
startswith
(
'
:
'
):
continue
entry
=
l
continue
f
=
l
if
f
not
in
seen
:
seen
[
f
]
=
1
entry
=
entry
.
split
()
h
=
entry
[
3
]
p
=
(
entry
[
1
]
==
"
100755
"
)
s
=
(
entry
[
1
]
==
"
120000
"
)
self
.
modecache
[(
f
,
h
)]
=
(
p
and
"
x
"
)
or
(
s
and
"
l
"
)
or
""
changes
.
append
((
f
,
h
))
entry
=
None
return
(
changes
,
{})
def
getcommit
(
self
,
version
):
c
=
self
.
catfile
(
version
,
"
commit
"
)
# read the commit hash
end
=
c
.
find
(
"
\n\n
"
)
message
=
c
[
end
+
2
:]
message
=
self
.
recode
(
message
)
l
=
c
[:
end
].
splitlines
()
manifest
=
l
[
0
].
split
()[
1
]
parents
=
[]
for
e
in
l
[
1
:]:
n
,
v
=
e
.
split
(
"
"
,
1
)
if
n
==
"
author
"
:
p
=
v
.
split
()
tm
,
tz
=
p
[
-
2
:]
author
=
"
"
.
join
(
p
[:
-
2
])
if
author
[
0
]
==
"
<
"
:
author
=
author
[
1
:
-
1
]
author
=
self
.
recode
(
author
)
if
n
==
"
committer
"
:
p
=
v
.
split
()
tm
,
tz
=
p
[
-
2
:]
committer
=
"
"
.
join
(
p
[:
-
2
])
if
committer
[
0
]
==
"
<
"
:
committer
=
committer
[
1
:
-
1
]
committer
=
self
.
recode
(
committer
)
message
+=
"
\n
committer: %s
\n
"
%
committer
if
n
==
"
parent
"
:
parents
.
append
(
v
)
tzs
,
tzh
,
tzm
=
tz
[
-
5
:
-
4
]
+
"
1
"
,
tz
[
-
4
:
-
2
],
tz
[
-
2
:]
tz
=
-
int
(
tzs
)
*
(
int
(
tzh
)
*
3600
+
int
(
tzm
))
date
=
tm
+
"
"
+
str
(
tz
)
c
=
commit
(
parents
=
parents
,
date
=
date
,
author
=
author
,
desc
=
message
,
rev
=
version
)
return
c
def
gettags
(
self
):
tags
=
{}
fh
=
self
.
gitcmd
(
'
git ls-remote --tags
"
%s
"'
%
self
.
path
)
prefix
=
'
refs/tags/
'
for
line
in
fh
:
line
=
line
.
strip
()
if
not
line
.
endswith
(
"
^{}
"
):
continue
node
,
tag
=
line
.
split
(
None
,
1
)
if
not
tag
.
startswith
(
prefix
):
continue
tag
=
tag
[
len
(
prefix
):
-
3
]
tags
[
tag
]
=
node
return
tags
def
getchangedfiles
(
self
,
version
,
i
):
changes
=
[]
if
i
is
None
:
fh
=
self
.
gitcmd
(
"
git diff-tree --root -m -r %s
"
%
version
)
for
l
in
fh
:
if
"
\t
"
not
in
l
:
continue
m
,
f
=
l
[:
-
1
].
split
(
"
\t
"
)
changes
.
append
(
f
)
fh
.
close
()
else
:
fh
=
self
.
gitcmd
(
'
git diff-tree --name-only --root -r %s
"
%s^%s
"
--
'
%
(
version
,
version
,
i
+
1
))
changes
=
[
f
.
rstrip
(
'
\n
'
)
for
f
in
fh
]
fh
.
close
()
return
changes
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment