tests/test-help.out
Add support for cloning with hardlinks on windows.
In order to use hardlinks, the win32file module is needed, and this is
present in ActivePython. If it isn't present, or hardlinks are not supported
on the underlying filesystem, a regular copy is used.
When using hardlinks the biggest benefit is probably the saving in space,
but cloning can be much quicker. For example cloning the Xen tree
(non trivial) without an update goes from about 95s to 15s.
Unix-like platforms should be unaffected, although should be more tolerant on
filesystems that don't support hard links.
(tweaked by mpm to deal with new copyfiles function)
--- hg.orig/mercurial/commands.py 2005-09-13 19:32:53.000000000 -0500
+++ hg/mercurial/commands.py 2005-09-14 12:11:34.000000000 -0500
@@ -620,10 +620,6 @@ def clone(ui, source, dest=None, **opts)
if other.dev() != -1:
abspath = os.path.abspath(source)
- copyfile = (os.stat(dest).st_dev == other.dev()
- and getattr(os, 'link', None) or shutil.copy2)
- if copyfile is not shutil.copy2:
- ui.note("cloning by hardlink\n")
# we use a lock here because if we race with commit, we can
# end up with extra data in the cloned revlogs that's not
@@ -638,7 +634,7 @@ def clone(ui, source, dest=None, **opts)
for f in files.split():
src = os.path.join(source, ".hg", f)
dst = os.path.join(dest, ".hg", f)
- util.copyfiles(src, dst, copyfile)
+ util.copyfiles(src, dst)
repo = hg.repository(ui, dest)
Index: hg/mercurial/util.py
===================================================================
--- hg.orig/mercurial/util.py 2005-09-08 00:15:25.000000000 -0500
+++ hg/mercurial/util.py 2005-09-14 12:16:49.000000000 -0500
@@ -12,7 +12,7 @@ platform-specific details from the core.
import os, errno
from demandload import *
-demandload(globals(), "re cStringIO")
+demandload(globals(), "re cStringIO shutil")
def binary(s):
"""return true if a string is binary data using diff's heuristic"""
@@ -217,17 +217,28 @@ def rename(src, dst):
os.unlink(dst)
os.rename(src, dst)
-def copyfiles(src, dst, copyfile):
- """Copy a directory tree, files are copied using 'copyfile'."""
+def copyfiles(src, dst, hardlink=None):
+ """Copy a directory tree using hardlinks if possible"""
+
+ if hardlink is None:
+ hardlink = (os.stat(src).st_dev ==
+ os.stat(os.path.dirname(dst)).st_dev)
if os.path.isdir(src):
os.mkdir(dst)
for name in os.listdir(src):
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
- copyfiles(srcname, dstname, copyfile)
+ copyfiles(srcname, dstname, hardlink)
else:
- copyfile(src, dst)
+ if hardlink:
+ try:
+ os_link(src, dst)
+ except:
+ hardlink = False
+ shutil.copy2(src, dst)
+ else:
+ shutil.copy2(src, dst)
def opener(base):
"""
@@ -244,13 +255,13 @@ def opener(base):
if mode[0] != "r":
try:
- s = os.stat(f)
+ nlink = nlinks(f)
except OSError:
d = os.path.dirname(f)
if not os.path.isdir(d):
os.makedirs(d)
else:
- if s.st_nlink > 1:
+ if nlink > 1:
file(f + ".tmp", "wb").write(file(f, "rb").read())
rename(f+".tmp", f)
@@ -266,10 +277,41 @@ def _makelock_file(info, pathname):
def _readlock_file(pathname):
return file(pathname).read()
+def nlinks(pathname):
+ """Return number of hardlinks for the given file."""
+ return os.stat(pathname).st_nlink
+
+if hasattr(os, 'link'):
+ os_link = os.link
+else:
+ def os_link(src, dst):
+ raise OSError(0, "Hardlinks not supported")
+
# Platform specific variants
if os.name == 'nt':
nulldev = 'NUL:'
+ try: # ActivePython can create hard links using win32file module
+ import win32file
+
+ def os_link(src, dst): # NB will only succeed on NTFS
+ win32file.CreateHardLink(dst, src)
+
+ def nlinks(pathname):
+ """Return number of hardlinks for the given file."""
+ try:
+ fh = win32file.CreateFile(pathname,
+ win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
+ None, win32file.OPEN_EXISTING, 0, None)
+ res = win32file.GetFileInformationByHandle(fh)
+ fh.Close()
+ return res[7]
+ except:
+ return os.stat(pathname).st_nlink
+
+ except ImportError:
+ pass
+
def is_exec(f, last):
return last
Mercurial Distributed SCM
basic commands (use "hg help" for the full list or option "-v" for details):
add add the specified files on the next commit
annotate show changeset information per file line
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
diff diff working directory (or selected files)
export dump the header and diffs for one or more changesets
init create a new repository in the given directory
log show revision history of entire repository or files
pull pull changes from the specified source
push push changes to the specified destination
remove remove the specified files on the next commit
revert revert modified files or dirs back to their unmodified states
serve export the repository via HTTP
status show changed files in the working directory
update update or merge working directory
add add the specified files on the next commit
annotate show changeset information per file line
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
diff diff working directory (or selected files)
export dump the header and diffs for one or more changesets
init create a new repository in the given directory
log show revision history of entire repository or files
pull pull changes from the specified source
push push changes to the specified destination
remove remove the specified files on the next commit
revert revert modified files or dirs back to their unmodified states
serve export the repository via HTTP
status show changed files in the working directory
update update or merge working directory
Mercurial Distributed SCM
list of commands (use "hg help -v" to show aliases and global options):
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information per file line
bundle create a changegroup file
cat output the latest or given revision of a file
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
copy mark a file as copied or renamed for the next commit
diff diff working directory (or selected files)
export dump the header and diffs for one or more changesets
forget don't add the specified files on the next commit
grep search for a pattern in specified files and revisions
heads show current repository heads
help show help for a given command or all commands
identify print information about the working copy
import import an ordered set of patches
incoming show new changesets found in source
init create a new repository in the given directory
locate locate files matching specific patterns
log show revision history of entire repository or files
manifest output the latest or given revision of the project manifest
outgoing show changesets not found in destination
parents show the parents of the working dir or revision
paths show definition of symbolic path names
pull pull changes from the specified source
push push changes to the specified destination
rawcommit raw commit interface
recover roll back an interrupted transaction
remove remove the specified files on the next commit
revert revert modified files or dirs back to their unmodified states
root print the root (top) of the current working dir
serve export the repository via HTTP
status show changed files in the working directory
tag add a tag for the current tip or a given revision
tags list repository tags
tip show the tip revision
unbundle apply a changegroup file
undo undo the last commit or pull
update update or merge working directory
verify verify the integrity of the repository
version output version and copyright information
add add the specified files on the next commit
addremove add all new files, delete all missing files
annotate show changeset information per file line
bundle create a changegroup file
cat output the latest or given revision of a file
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
copy mark a file as copied or renamed for the next commit
diff diff working directory (or selected files)
export dump the header and diffs for one or more changesets
forget don't add the specified files on the next commit
grep search for a pattern in specified files and revisions
heads show current repository heads
help show help for a given command or all commands
identify print information about the working copy
import import an ordered set of patches
incoming show new changesets found in source
init create a new repository in the given directory
locate locate files matching specific patterns
log show revision history of entire repository or files
manifest output the latest or given revision of the project manifest
outgoing show changesets not found in destination
parents show the parents of the working dir or revision
paths show definition of symbolic path names
pull pull changes from the specified source
push push changes to the specified destination
rawcommit raw commit interface
recover roll back an interrupted transaction
remove remove the specified files on the next commit
revert revert modified files or dirs back to their unmodified states
root print the root (top) of the current working dir
serve export the repository via HTTP
status show changed files in the working directory
tag add a tag for the current tip or a given revision
tags list repository tags
tip show the tip revision
unbundle apply a changegroup file
undo undo the last commit or pull
update update or merge working directory
verify verify the integrity of the repository
version output version and copyright information
hg add [OPTION]... [FILE]...
add the specified files on the next commit
options:
-I --include include path in search
-X --exclude exclude path from search
hg add: option --skjdfks not recognized
hg add [OPTION]... [FILE]...
add the specified files on the next commit
options:
-I --include include path in search
-X --exclude exclude path from search
hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...
diff working directory (or selected files)
options:
-r --rev revision
-a --text treat all files as text
-I --include include path in search
-X --exclude exclude path from search
hg status [OPTION]... [FILE]...
show changed files in the working directory
M = modified
A = added
R = removed
? = not tracked
options:
-m --modified show only modified files
-a --added show only added files
-r --removed show only removed files
-u --unknown show only unknown (not tracked) files
-n --no-status hide status prefix
-0 --print0 end filenames with NUL
-I --include include path in search
-X --exclude exclude path from search
hg status [OPTION]... [FILE]...
show changed files in the working directory
hg: unknown command 'foo'
Mercurial Distributed SCM
basic commands (use "hg help" for the full list or option "-v" for details):
add add the specified files on the next commit
annotate show changeset information per file line
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
diff diff working directory (or selected files)
export dump the header and diffs for one or more changesets
init create a new repository in the given directory
log show revision history of entire repository or files
pull pull changes from the specified source
push push changes to the specified destination
remove remove the specified files on the next commit
revert revert modified files or dirs back to their unmodified states
serve export the repository via HTTP
status show changed files in the working directory
update update or merge working directory
hg: unknown command 'skjdfks'
Mercurial Distributed SCM
basic commands (use "hg help" for the full list or option "-v" for details):
add add the specified files on the next commit
annotate show changeset information per file line
clone make a copy of an existing repository
commit commit the specified files or all outstanding changes
diff diff working directory (or selected files)
export dump the header and diffs for one or more changesets
init create a new repository in the given directory
log show revision history of entire repository or files
pull pull changes from the specified source
push push changes to the specified destination
remove remove the specified files on the next commit
revert revert modified files or dirs back to their unmodified states
serve export the repository via HTTP
status show changed files in the working directory
update update or merge working directory