--- a/hgext/largefiles/lfutil.py Tue Sep 25 16:01:08 2012 +0400
+++ b/hgext/largefiles/lfutil.py Thu Sep 27 15:50:14 2012 -0500
@@ -141,7 +141,7 @@
def normallookup(self, f):
return super(largefilesdirstate, self).normallookup(unixpath(f))
-def openlfdirstate(ui, repo):
+def openlfdirstate(ui, repo, create=True):
'''
Return a dirstate object that tracks largefiles: i.e. its root is
the repo root, but it is saved in .hg/largefiles/dirstate.
@@ -154,7 +154,7 @@
# If the largefiles dirstate does not exist, populate and create
# it. This ensures that we create it on the first meaningful
# largefiles operation in a new clone.
- if not os.path.exists(os.path.join(admin, 'dirstate')):
+ if create and not os.path.exists(os.path.join(admin, 'dirstate')):
util.makedirs(admin)
matcher = getstandinmatcher(repo)
for standin in dirstatewalk(repo.dirstate, matcher):
@@ -435,8 +435,11 @@
return util.pconvert(os.path.normpath(path))
def islfilesrepo(repo):
- return ('largefiles' in repo.requirements and
- util.any(shortname + '/' in f[0] for f in repo.store.datafiles()))
+ if ('largefiles' in repo.requirements and
+ util.any(shortname + '/' in f[0] for f in repo.store.datafiles())):
+ return True
+
+ return util.any(openlfdirstate(repo.ui, repo, False))
class storeprotonotcapable(Exception):
def __init__(self, storetypes):
--- a/hgext/largefiles/overrides.py Tue Sep 25 16:01:08 2012 +0400
+++ b/hgext/largefiles/overrides.py Thu Sep 27 15:50:14 2012 -0500
@@ -1018,11 +1018,12 @@
else:
ui.status(_('largefiles: %d to upload\n') % len(toupload))
-def overrideaddremove(orig, ui, repo, *pats, **opts):
+def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
+ similarity=None):
if not lfutil.islfilesrepo(repo):
- return orig(ui, repo, *pats, **opts)
+ return orig(repo, pats, opts, dry_run, similarity)
# Get the list of missing largefiles so we can remove them
- lfdirstate = lfutil.openlfdirstate(ui, repo)
+ lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
False, False)
(unsure, modified, added, removed, missing, unknown, ignored, clean) = s
@@ -1034,16 +1035,16 @@
if missing:
m = [repo.wjoin(f) for f in missing]
repo._isaddremove = True
- removelargefiles(ui, repo, *m, **opts)
+ removelargefiles(repo.ui, repo, *m, **opts)
repo._isaddremove = False
# Call into the normal add code, and any files that *should* be added as
# largefiles will be
- addlargefiles(ui, repo, *pats, **opts)
+ addlargefiles(repo.ui, repo, *pats, **opts)
# Now that we've handled largefiles, hand off to the original addremove
# function to take care of the rest. Make sure it doesn't do anything with
# largefiles by installing a matcher that will ignore them.
installnormalfilesmatchfn(repo[None].manifest())
- result = orig(ui, repo, *pats, **opts)
+ result = orig(repo, pats, opts, dry_run, similarity)
restorematchfn()
return result
--- a/hgext/largefiles/uisetup.py Tue Sep 25 16:01:08 2012 +0400
+++ b/hgext/largefiles/uisetup.py Thu Sep 27 15:50:14 2012 -0500
@@ -9,7 +9,7 @@
'''setup for largefiles extension: uisetup'''
from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
- httppeer, localrepo, merge, sshpeer, sshserver, wireproto
+ httppeer, localrepo, merge, scmutil, sshpeer, sshserver, wireproto
from mercurial.i18n import _
from mercurial.hgweb import hgweb_mod, protocol, webcommands
from mercurial.subrepo import hgsubrepo
@@ -30,8 +30,10 @@
'(default: 10)'))]
entry[1].extend(addopt)
- entry = extensions.wrapcommand(commands.table, 'addremove',
- overrides.overrideaddremove)
+ # The scmutil function is called both by the (trivial) addremove command,
+ # and in the process of handling commit -A (issue3542)
+ entry = extensions.wrapfunction(scmutil, 'addremove',
+ overrides.scmutiladdremove)
entry = extensions.wrapcommand(commands.table, 'remove',
overrides.overrideremove)
entry = extensions.wrapcommand(commands.table, 'forget',
--- a/mercurial/archival.py Tue Sep 25 16:01:08 2012 +0400
+++ b/mercurial/archival.py Thu Sep 27 15:50:14 2012 -0500
@@ -12,6 +12,7 @@
import scmutil, util, encoding
import cStringIO, os, tarfile, time, zipfile
import zlib, gzip
+import struct
def tidyprefix(dest, kind, prefix):
'''choose prefix to use for names in archive. make sure prefix is
@@ -165,6 +166,7 @@
if mtime < epoch:
mtime = epoch
+ self.mtime = mtime
self.date_time = time.gmtime(mtime)[:6]
def addfile(self, name, mode, islink, data):
@@ -178,6 +180,14 @@
mode = 0777
ftype = 0xa000 # UNX_IFLNK in unzip source code
i.external_attr = (mode | ftype) << 16L
+ # add "extended-timestamp" extra block, because zip archives
+ # without this will be extracted with unexpected timestamp,
+ # if TZ is not configured as GMT
+ i.extra += struct.pack('<hhBl',
+ 0x5455, # block type: "extended-timestamp"
+ 1 + 4, # size of this block
+ 1, # "modification time is present"
+ self.mtime) # time of last modification (UTC)
self.z.writestr(i, data)
def done(self):
--- a/tests/test-archive.t Tue Sep 25 16:01:08 2012 +0400
+++ b/tests/test-archive.t Thu Sep 27 15:50:14 2012 -0500
@@ -270,3 +270,31 @@
\s*147\s+2 files (re)
$ cd ..
+
+issue3600: check whether "hg archive" can create archive files which
+are extracted with expected timestamp, even though TZ is not
+configured as GMT.
+
+ $ mkdir issue3600
+ $ cd issue3600
+
+ $ hg init repo
+ $ echo a > repo/a
+ $ hg -R repo add repo/a
+ $ hg -R repo commit -m '#0' -d '456789012 21600'
+ $ cat > show_mtime.py <<EOF
+ > import sys, os
+ > print int(os.stat(sys.argv[1]).st_mtime)
+ > EOF
+
+ $ hg -R repo archive --prefix tar-extracted archive.tar
+ $ (TZ=UTC-3; export TZ; tar xf archive.tar)
+ $ python show_mtime.py tar-extracted/a
+ 456789012
+
+ $ hg -R repo archive --prefix zip-extracted archive.zip
+ $ (TZ=UTC-3; export TZ; unzip -q archive.zip)
+ $ python show_mtime.py zip-extracted/a
+ 456789012
+
+ $ cd ..
--- a/tests/test-largefiles.t Tue Sep 25 16:01:08 2012 +0400
+++ b/tests/test-largefiles.t Thu Sep 27 15:50:14 2012 -0500
@@ -543,6 +543,33 @@
C sub2/large6
C sub2/large7
+Test commit -A (issue 3542)
+ $ echo large8 > large8
+ $ hg add --large large8
+ $ hg ci -Am 'this used to add large8 as normal and commit both'
+ Invoking status precommit hook
+ A large8
+ Invoking status postcommit hook
+ C large8
+ C normal
+ C normal3
+ C sub/large4
+ C sub/normal4
+ C sub2/large6
+ C sub2/large7
+ $ rm large8
+ $ hg ci -Am 'this used to not notice the rm'
+ removing large8
+ Invoking status precommit hook
+ R large8
+ Invoking status postcommit hook
+ C normal
+ C normal3
+ C sub/large4
+ C sub/normal4
+ C sub2/large6
+ C sub2/large7
+
Test that a standin can't be added as a large file
$ touch large
@@ -588,8 +615,19 @@
date: Thu Jan 01 00:00:00 1970 +0000
summary: removed large
+ changeset: 13:0a3e75774479
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: this used to add large8 as normal and commit both
+
+ changeset: 14:84f3d378175c
+ user: test
+ date: Thu Jan 01 00:00:00 1970 +0000
+ summary: this used to not notice the rm
+
searching for changes
largefiles to upload:
+ large8
large
foo
@@ -1545,3 +1583,40 @@
lf_subrepo_archive/subrepo/normal.txt
$ cd ..
+
+Test that addremove picks up largefiles prior to the initial commit (issue3541)
+
+ $ hg init addrm2
+ $ cd addrm2
+ $ touch large.dat
+ $ touch large2.dat
+ $ touch normal
+ $ hg add --large large.dat
+ $ hg addremove -v
+ adding large2.dat as a largefile
+ adding normal
+
+Test that forgetting all largefiles reverts to islfilesrepo() == False
+(addremove will add *.dat as normal files now)
+ $ hg forget large.dat
+ $ hg forget large2.dat
+ $ hg addremove -v
+ adding large.dat
+ adding large2.dat
+
+Test commit's addremove option prior to the first commit
+ $ hg forget large.dat
+ $ hg forget large2.dat
+ $ hg add --large large.dat
+ $ hg ci -Am "commit"
+ adding large2.dat as a largefile
+ Invoking status precommit hook
+ A large.dat
+ A large2.dat
+ A normal
+ $ find .hglf/ | sort
+ .hglf/
+ .hglf/large.dat
+ .hglf/large2.dat
+
+ $ cd ..