annotate hgext/largefiles/lfutil.py @ 17659:ae57920ac188 stable

largefiles: enable islfilesrepo() prior to a commit (issue3541) Previously, even if a file was added with --large, 'hg addremove' or 'hg ci -A' would add all files (including the previously added large files) as normal files. Only after a commit where a file was added with --large would subsequent adds or 'ci -A' take into account the minsize or the pattern configuration. This change more closely follows the help for largefiles, which mentions that 'add --large' is required to enable the configuration, but doesn't mention the previously required commit. Also, if 'hg add --large' was performed and then 'hg forget <file>' (both before a largefile enabling commit), the forget command would error out saying '.hglf/<file> not tracked'. This is also fixed. This reports that a repo is largefiles enabled as soon as a file is added with --large, which enables 'add', 'addremove' and 'ci -A' to honor the config settings before the first commit. Note that prior to the next commit, if all largefiles are forgotten, the repository goes back to reporting the repo as not largefiles enabled. It makes no sense to handle this by adding a --large option to 'addremove', because then it would also be needed for 'commit', but only when '-A' is specified. While this gets around the awkwardness of having to add a largefile, then commit it, and then addremove the other files when importing an existing codebase (and preserving that extra commit in permanent history), it does still require finding and manually adding one of the files as --large. Therefore it is probably desirable to have a --large option for init as well.
author Matt Harbison <matt_harbison@yahoo.com>
date Mon, 30 Jul 2012 20:56:41 -0400
parents 32246faba53a
children 67deea9c1c42
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
1 # Copyright 2009-2010 Gregory P. Ward
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
3 # Copyright 2010-2011 Fog Creek Software
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
4 # Copyright 2010-2011 Unity Technologies
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
5 #
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
6 # This software may be used and distributed according to the terms of the
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
7 # GNU General Public License version 2 or any later version.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
8
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
9 '''largefiles utility code: must not import other modules in this package.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
10
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
11 import os
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
12 import errno
15320
681267a5f491 largefiles: use XDG and OS X-specific cache locations by default (issue3067)
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15319
diff changeset
13 import platform
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
14 import shutil
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
15 import stat
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
16
15226
2223ea21c98f largefiles: cleanup import, now that we can assume > 1.9 for bundled extension
Na'Tosha Bard <natosha@unity3d.com>
parents: 15224
diff changeset
17 from mercurial import dirstate, httpconnection, match as match_, util, scmutil
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
18 from mercurial.i18n import _
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
19
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
20 shortname = '.hglf'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
21 longname = 'largefiles'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
22
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
23
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
24 # -- Portability wrappers ----------------------------------------------
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
25
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
26 def dirstatewalk(dirstate, matcher, unknown=False, ignored=False):
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
27 return dirstate.walk(matcher, [], unknown, ignored)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
28
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
29 def repoadd(repo, list):
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
30 add = repo[None].add
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
31 return add(list)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
32
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
33 def reporemove(repo, list, unlink=False):
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
34 def remove(list, unlink):
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
35 wlock = repo.wlock()
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
36 try:
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
37 if unlink:
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
38 for f in list:
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
39 try:
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
40 util.unlinkpath(repo.wjoin(f))
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
41 except OSError, inst:
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
42 if inst.errno != errno.ENOENT:
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
43 raise
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
44 repo[None].forget(list)
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
45 finally:
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
46 wlock.release()
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
47 return remove(list, unlink=unlink)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
48
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
49 def repoforget(repo, list):
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
50 forget = repo[None].forget
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
51 return forget(list)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
52
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
53 def findoutgoing(repo, remote, force):
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
54 from mercurial import discovery
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
55 common, _anyinc, _heads = discovery.findcommonincoming(repo,
17270
32246faba53a largefiles: fix a traceback introduced with recent peer changes
Matt Harbison <matt_harbison@yahoo.com>
parents: 16928
diff changeset
56 remote.peer(), force=force)
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
57 return repo.changelog.findmissing(common)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
58
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
59 # -- Private worker functions ------------------------------------------
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
60
15227
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
61 def getminsize(ui, assumelfiles, opt, default=10):
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
62 lfsize = opt
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
63 if not lfsize and assumelfiles:
15304
9aa9d4bb3d88 largefiles: rename config setting 'size' to 'minsize'
Greg Ward <greg@gerg.ca>
parents: 15255
diff changeset
64 lfsize = ui.config(longname, 'minsize', default=default)
15227
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
65 if lfsize:
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
66 try:
15228
ee625de3541e largefiles: allow minimum size to be a float
Greg Ward <greg@gerg.ca>
parents: 15227
diff changeset
67 lfsize = float(lfsize)
15227
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
68 except ValueError:
15228
ee625de3541e largefiles: allow minimum size to be a float
Greg Ward <greg@gerg.ca>
parents: 15227
diff changeset
69 raise util.Abort(_('largefiles: size must be number (not %s)\n')
15227
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
70 % lfsize)
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
71 if lfsize is None:
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
72 raise util.Abort(_('minimum size for largefiles must be specified'))
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
73 return lfsize
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15226
diff changeset
74
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
75 def link(src, dest):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
76 try:
15206
f85c76b16f27 largefiles: fix commit of specified file on non-windows
Na'Tosha Bard <natosha@unity3d.com>
parents: 15188
diff changeset
77 util.oslink(src, dest)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
78 except OSError:
15572
926bc23d0b6a largefiles: copy files into .hg/largefiles atomically
Martin Geisler <mg@aragost.com>
parents: 15571
diff changeset
79 # if hardlinks fail, fallback on atomic copy
926bc23d0b6a largefiles: copy files into .hg/largefiles atomically
Martin Geisler <mg@aragost.com>
parents: 15571
diff changeset
80 dst = util.atomictempfile(dest)
15699
84e55467093c largefiles: copy files in binary mode (issue3164)
Matt Mackall <mpm@selenic.com>
parents: 15658
diff changeset
81 for chunk in util.filechunkiter(open(src, 'rb')):
15572
926bc23d0b6a largefiles: copy files into .hg/largefiles atomically
Martin Geisler <mg@aragost.com>
parents: 15571
diff changeset
82 dst.write(chunk)
926bc23d0b6a largefiles: copy files into .hg/largefiles atomically
Martin Geisler <mg@aragost.com>
parents: 15571
diff changeset
83 dst.close()
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
84 os.chmod(dest, os.stat(src).st_mode)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
85
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
86 def usercachepath(ui, hash):
15350
8b8dd13295db largefiles: use ui.configpath() where appropriate
Greg Ward <greg@gerg.ca>
parents: 15349
diff changeset
87 path = ui.configpath(longname, 'usercache', None)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
88 if path:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
89 path = os.path.join(path, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
90 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
91 if os.name == 'nt':
15255
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
92 appdata = os.getenv('LOCALAPPDATA', os.getenv('APPDATA'))
15658
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
93 if appdata:
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
94 path = os.path.join(appdata, longname, hash)
15320
681267a5f491 largefiles: use XDG and OS X-specific cache locations by default (issue3067)
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15319
diff changeset
95 elif platform.system() == 'Darwin':
15658
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
96 home = os.getenv('HOME')
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
97 if home:
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
98 path = os.path.join(home, 'Library', 'Caches',
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
99 longname, hash)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
100 elif os.name == 'posix':
15320
681267a5f491 largefiles: use XDG and OS X-specific cache locations by default (issue3067)
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15319
diff changeset
101 path = os.getenv('XDG_CACHE_HOME')
681267a5f491 largefiles: use XDG and OS X-specific cache locations by default (issue3067)
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15319
diff changeset
102 if path:
681267a5f491 largefiles: use XDG and OS X-specific cache locations by default (issue3067)
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15319
diff changeset
103 path = os.path.join(path, longname, hash)
681267a5f491 largefiles: use XDG and OS X-specific cache locations by default (issue3067)
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15319
diff changeset
104 else:
15658
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
105 home = os.getenv('HOME')
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
106 if home:
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
107 path = os.path.join(home, '.cache', longname, hash)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
108 else:
15253
67d010779907 largefiles: improve error reporting
Greg Ward <greg@gerg.ca>
parents: 15252
diff changeset
109 raise util.Abort(_('unknown operating system: %s\n') % os.name)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
110 return path
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
111
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
112 def inusercache(ui, hash):
15658
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
113 path = usercachepath(ui, hash)
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
114 return path and os.path.exists(path)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
115
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
116 def findfile(repo, hash):
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
117 if instore(repo, hash):
16928
73b9286e667c largefiles: lowercase messages
Martin Geisler <mg@aragost.com>
parents: 16247
diff changeset
118 repo.ui.note(_('found %s in store\n') % hash)
15913
c35dcde25174 largefiles: refactor lfutil.findfiles to be more logical
Na'Tosha Bard <natosha@unity3d.com>
parents: 15796
diff changeset
119 return storepath(repo, hash)
15317
41f371150ccb largefiles: make the store primary, and the user cache secondary
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15316
diff changeset
120 elif inusercache(repo.ui, hash):
16928
73b9286e667c largefiles: lowercase messages
Martin Geisler <mg@aragost.com>
parents: 16247
diff changeset
121 repo.ui.note(_('found %s in system cache\n') % hash)
15408
db8b0ee74025 largefiles: ensure destination directory exists before findfile links to there
Hao Lian <hao@fogcreek.com>
parents: 15392
diff changeset
122 path = storepath(repo, hash)
db8b0ee74025 largefiles: ensure destination directory exists before findfile links to there
Hao Lian <hao@fogcreek.com>
parents: 15392
diff changeset
123 util.makedirs(os.path.dirname(path))
db8b0ee74025 largefiles: ensure destination directory exists before findfile links to there
Hao Lian <hao@fogcreek.com>
parents: 15392
diff changeset
124 link(usercachepath(repo.ui, hash), path)
15913
c35dcde25174 largefiles: refactor lfutil.findfiles to be more logical
Na'Tosha Bard <natosha@unity3d.com>
parents: 15796
diff changeset
125 return path
c35dcde25174 largefiles: refactor lfutil.findfiles to be more logical
Na'Tosha Bard <natosha@unity3d.com>
parents: 15796
diff changeset
126 return None
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
127
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
128 class largefilesdirstate(dirstate.dirstate):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
129 def __getitem__(self, key):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
130 return super(largefilesdirstate, self).__getitem__(unixpath(key))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
131 def normal(self, f):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
132 return super(largefilesdirstate, self).normal(unixpath(f))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
133 def remove(self, f):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
134 return super(largefilesdirstate, self).remove(unixpath(f))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
135 def add(self, f):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
136 return super(largefilesdirstate, self).add(unixpath(f))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
137 def drop(self, f):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
138 return super(largefilesdirstate, self).drop(unixpath(f))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
139 def forget(self, f):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
140 return super(largefilesdirstate, self).forget(unixpath(f))
15793
3ef07ecdb0d5 largefiles: correctly handle dirstate status when rebasing
Na'Tosha Bard <natosha@unity3d.com>
parents: 15700
diff changeset
141 def normallookup(self, f):
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
142 return super(largefilesdirstate, self).normallookup(unixpath(f))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
143
17659
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
144 def openlfdirstate(ui, repo, create=True):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
145 '''
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
146 Return a dirstate object that tracks largefiles: i.e. its root is
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
147 the repo root, but it is saved in .hg/largefiles/dirstate.
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
148 '''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
149 admin = repo.join(longname)
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
150 opener = scmutil.opener(admin)
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
151 lfdirstate = largefilesdirstate(opener, ui, repo.root,
15349
63455eb771af largefiles: drop more unnecessary compatibility checks
Greg Ward <greg@gerg.ca>
parents: 15347
diff changeset
152 repo.dirstate._validate)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
153
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
154 # If the largefiles dirstate does not exist, populate and create
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
155 # it. This ensures that we create it on the first meaningful
15794
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
156 # largefiles operation in a new clone.
17659
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
157 if create and not os.path.exists(os.path.join(admin, 'dirstate')):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
158 util.makedirs(admin)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
159 matcher = getstandinmatcher(repo)
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
160 for standin in dirstatewalk(repo.dirstate, matcher):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
161 lfile = splitstandin(standin)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
162 hash = readstandin(repo, lfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
163 lfdirstate.normallookup(lfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
164 try:
15553
e89385e4ef8d largefiles: file storage should be relative to repo, not relative to cwd
Mads Kiilerich <mads@kiilerich.com>
parents: 15548
diff changeset
165 if hash == hashfile(repo.wjoin(lfile)):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
166 lfdirstate.normal(lfile)
15548
f76584098c88 largefiles: fix 'hg clone . ../foo' OSError abort
Martin Geisler <mg@lazybytes.net>
parents: 15408
diff changeset
167 except OSError, err:
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
168 if err.errno != errno.ENOENT:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
169 raise
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
170 return lfdirstate
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
171
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
172 def lfdirstatestatus(lfdirstate, repo, rev):
15794
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
173 match = match_.always(repo.root, repo.getcwd())
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
174 s = lfdirstate.status(match, [], False, False, False)
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
175 unsure, modified, added, removed, missing, unknown, ignored, clean = s
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
176 for lfile in unsure:
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
177 if repo[rev][standin(lfile)].data().strip() != \
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
178 hashfile(repo.wjoin(lfile)):
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
179 modified.append(lfile)
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
180 else:
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
181 clean.append(lfile)
0d91211dd12f largefiles: fix inappropriate locking (issue3182)
Levi Bard <levi@unity3d.com>
parents: 15793
diff changeset
182 lfdirstate.normal(lfile)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
183 return (modified, added, removed, missing, unknown, ignored, clean)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
184
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
185 def listlfiles(repo, rev=None, matcher=None):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
186 '''return a list of largefiles in the working copy or the
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
187 specified changeset'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
188
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
189 if matcher is None:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
190 matcher = getstandinmatcher(repo)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
191
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
192 # ignore unknown files in working directory
15255
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
193 return [splitstandin(f)
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
194 for f in repo[rev].walk(matcher)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
195 if rev is not None or repo.dirstate[f] != '?']
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
196
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
197 def instore(repo, hash):
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
198 return os.path.exists(storepath(repo, hash))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
199
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
200 def storepath(repo, hash):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
201 return repo.join(os.path.join(longname, hash))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
202
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
203 def copyfromcache(repo, hash, filename):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
204 '''Copy the specified largefile from the repo or system cache to
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
205 filename in the repository. Return true on success or false if the
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
206 file was not found in either cache (which should not happened:
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
207 this is meant to be called only after ensuring that the needed
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
208 largefile exists in the cache).'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
209 path = findfile(repo, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
210 if path is None:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
211 return False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
212 util.makedirs(os.path.dirname(repo.wjoin(filename)))
15570
0f208626d503 largefiles: add comment about non-atomic working directory
Martin Geisler <mg@aragost.com>
parents: 15553
diff changeset
213 # The write may fail before the file is fully written, but we
0f208626d503 largefiles: add comment about non-atomic working directory
Martin Geisler <mg@aragost.com>
parents: 15553
diff changeset
214 # don't use atomic writes in the working copy.
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
215 shutil.copy(path, repo.wjoin(filename))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
216 return True
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
217
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
218 def copytostore(repo, rev, file, uploaded=False):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
219 hash = readstandin(repo, file)
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
220 if instore(repo, hash):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
221 return
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
222 copytostoreabsolute(repo, repo.wjoin(file), hash)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
223
15796
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
224 def copyalltostore(repo, node):
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
225 '''Copy all largefiles in a given revision to the store'''
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
226
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
227 ctx = repo[node]
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
228 for filename in ctx.files():
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
229 if isstandin(filename) and filename in ctx.manifest():
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
230 realfile = splitstandin(filename)
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
231 copytostore(repo, ctx.node(), realfile)
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
232
3e5b6045ccfc largefiles: factor out a copyalltostore() function
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 15794
diff changeset
233
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
234 def copytostoreabsolute(repo, file, hash):
15371
f26ed4ea46d8 largefiles: remove lfutil.createdir, replace calls with util.makedirs
Hao Lian <hao@fogcreek.com>
parents: 15350
diff changeset
235 util.makedirs(os.path.dirname(storepath(repo, hash)))
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
236 if inusercache(repo.ui, hash):
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
237 link(usercachepath(repo.ui, hash), storepath(repo, hash))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
238 else:
16153
05197f9fd1f3 largefiles: use repo.store.createmode for new files in .hg/largefiles
Martin Geisler <mg@aragost.com>
parents: 16103
diff changeset
239 dst = util.atomictempfile(storepath(repo, hash),
05197f9fd1f3 largefiles: use repo.store.createmode for new files in .hg/largefiles
Martin Geisler <mg@aragost.com>
parents: 16103
diff changeset
240 createmode=repo.store.createmode)
15699
84e55467093c largefiles: copy files in binary mode (issue3164)
Matt Mackall <mpm@selenic.com>
parents: 15658
diff changeset
241 for chunk in util.filechunkiter(open(file, 'rb')):
15571
809788118aa2 largefiles: write .hg/largefiles/ files atomically
Martin Geisler <mg@aragost.com>
parents: 15570
diff changeset
242 dst.write(chunk)
809788118aa2 largefiles: write .hg/largefiles/ files atomically
Martin Geisler <mg@aragost.com>
parents: 15570
diff changeset
243 dst.close()
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
244 linktousercache(repo, hash)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
245
15316
c65f5b6e26d4 largefiles: rename functions and methods to match desired behavior
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15304
diff changeset
246 def linktousercache(repo, hash):
15658
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
247 path = usercachepath(repo.ui, hash)
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
248 if path:
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
249 util.makedirs(os.path.dirname(path))
971c55ce03b8 largefiles: don't require a user cache (issue3088) (issue3155)
Kevin Gessner <kevin@fogcreek.com>
parents: 15572
diff changeset
250 link(storepath(repo, hash), path)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
251
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
252 def getstandinmatcher(repo, pats=[], opts={}):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
253 '''Return a match object that applies pats to the standin directory'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
254 standindir = repo.pathto(shortname)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
255 if pats:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
256 # patterns supplied: search standin directory relative to current dir
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
257 cwd = repo.getcwd()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
258 if os.path.isabs(cwd):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
259 # cwd is an absolute path for hg -R <reponame>
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
260 # work relative to the repository root in this case
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
261 cwd = ''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
262 pats = [os.path.join(standindir, cwd, pat) for pat in pats]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
263 elif os.path.isdir(standindir):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
264 # no patterns: relative to repo root
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
265 pats = [standindir]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
266 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
267 # no patterns and no standin dir: return matcher that matches nothing
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
268 match = match_.match(repo.root, None, [], exact=True)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
269 match.matchfn = lambda f: False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
270 return match
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
271 return getmatcher(repo, pats, opts, showbad=False)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
272
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
273 def getmatcher(repo, pats=[], opts={}, showbad=True):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
274 '''Wrapper around scmutil.match() that adds showbad: if false,
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
275 neuter the match object's bad() method so it does not print any
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
276 warnings about missing files or directories.'''
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
277 match = scmutil.match(repo[None], pats, opts)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
278
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
279 if not showbad:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
280 match.bad = lambda f, msg: None
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
281 return match
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
282
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
283 def composestandinmatcher(repo, rmatcher):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
284 '''Return a matcher that accepts standins corresponding to the
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
285 files accepted by rmatcher. Pass the list of files in the matcher
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
286 as the paths specified by the user.'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
287 smatcher = getstandinmatcher(repo, rmatcher.files())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
288 isstandin = smatcher.matchfn
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
289 def composedmatchfn(f):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
290 return isstandin(f) and rmatcher.matchfn(splitstandin(f))
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
291 smatcher.matchfn = composedmatchfn
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
292
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
293 return smatcher
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
294
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
295 def standin(filename):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
296 '''Return the repo-relative path to the standin for the specified big
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
297 file.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
298 # Notes:
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
299 # 1) Most callers want an absolute path, but _createstandin() needs
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
300 # it repo-relative so lfadd() can pass it to repoadd(). So leave
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
301 # it up to the caller to use repo.wjoin() to get an absolute path.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
302 # 2) Join with '/' because that's what dirstate always uses, even on
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
303 # Windows. Change existing separator to '/' first in case we are
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
304 # passed filenames from an external source (like the command line).
16066
6a42846cf769 i18n: use util.pconvert() instead of 'str.replace()' for problematic encoding
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15915
diff changeset
305 return shortname + '/' + util.pconvert(filename)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
306
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
307 def isstandin(filename):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
308 '''Return true if filename is a big file standin. filename must be
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
309 in Mercurial's internal form (slash-separated).'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
310 return filename.startswith(shortname + '/')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
311
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
312 def splitstandin(filename):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
313 # Split on / because that's what dirstate always uses, even on Windows.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
314 # Change local separator to / first just in case we are passed filenames
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
315 # from an external source (like the command line).
16066
6a42846cf769 i18n: use util.pconvert() instead of 'str.replace()' for problematic encoding
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15915
diff changeset
316 bits = util.pconvert(filename).split('/', 1)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
317 if len(bits) == 2 and bits[0] == shortname:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
318 return bits[1]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
319 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
320 return None
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
321
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
322 def updatestandin(repo, standin):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
323 file = repo.wjoin(splitstandin(standin))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
324 if os.path.exists(file):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
325 hash = hashfile(file)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
326 executable = getexecutable(file)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
327 writestandin(repo, standin, hash, executable)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
328
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
329 def readstandin(repo, filename, node=None):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
330 '''read hex hash from standin for filename at given node, or working
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
331 directory if no node is given'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
332 return repo[node][standin(filename)].data().strip()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
333
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
334 def writestandin(repo, standin, hash, executable):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
335 '''write hash to <repo.root>/<standin>'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
336 writehash(hash, repo.wjoin(standin), executable)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
337
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
338 def copyandhash(instream, outfile):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
339 '''Read bytes from instream (iterable) and write them to outfile,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
340 computing the SHA-1 hash of the data along the way. Close outfile
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
341 when done and return the binary hash.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
342 hasher = util.sha1('')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
343 for data in instream:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
344 hasher.update(data)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
345 outfile.write(data)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
346
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
347 # Blecch: closing a file that somebody else opened is rude and
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
348 # wrong. But it's so darn convenient and practical! After all,
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
349 # outfile was opened just to copy and hash.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
350 outfile.close()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
351
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
352 return hasher.digest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
353
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
354 def hashrepofile(repo, file):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
355 return hashfile(repo.wjoin(file))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
356
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
357 def hashfile(file):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
358 if not os.path.exists(file):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
359 return ''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
360 hasher = util.sha1('')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
361 fd = open(file, 'rb')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
362 for data in blockstream(fd):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
363 hasher.update(data)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
364 fd.close()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
365 return hasher.hexdigest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
366
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
367 class limitreader(object):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
368 def __init__(self, f, limit):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
369 self.f = f
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
370 self.limit = limit
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
371
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
372 def read(self, length):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
373 if self.limit == 0:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
374 return ''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
375 length = length > self.limit and self.limit or length
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
376 self.limit -= length
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
377 return self.f.read(length)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
378
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
379 def close(self):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
380 pass
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
381
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
382 def blockstream(infile, blocksize=128 * 1024):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
383 """Generator that yields blocks of data from infile and closes infile."""
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
384 while True:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
385 data = infile.read(blocksize)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
386 if not data:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
387 break
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
388 yield data
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
389 # same blecch as copyandhash() above
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
390 infile.close()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
391
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
392 def writehash(hash, filename, executable):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
393 util.makedirs(os.path.dirname(filename))
15574
c9328c829cd9 largefiles: simplify lfutil.writehash
Martin Geisler <mg@aragost.com>
parents: 15572
diff changeset
394 util.writefile(filename, hash + '\n')
c9328c829cd9 largefiles: simplify lfutil.writehash
Martin Geisler <mg@aragost.com>
parents: 15572
diff changeset
395 os.chmod(filename, getmode(executable))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
396
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
397 def getexecutable(filename):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
398 mode = os.stat(filename).st_mode
15255
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
399 return ((mode & stat.S_IXUSR) and
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
400 (mode & stat.S_IXGRP) and
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
401 (mode & stat.S_IXOTH))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
402
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
403 def getmode(executable):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
404 if executable:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
405 return 0755
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
406 else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
407 return 0644
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
408
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
409 def urljoin(first, second, *arg):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
410 def join(left, right):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
411 if not left.endswith('/'):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
412 left += '/'
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
413 if right.startswith('/'):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
414 right = right[1:]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
415 return left + right
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
416
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
417 url = join(first, second)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
418 for a in arg:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
419 url = join(url, a)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
420 return url
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
421
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
422 def hexsha1(data):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
423 """hexsha1 returns the hex-encoded sha1 sum of the data in the file-like
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
424 object data"""
15347
799e56609ef6 largefiles: use util.sha1() instead of hashlib.sha1() everywhere
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15333
diff changeset
425 h = util.sha1()
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
426 for chunk in util.filechunkiter(data):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
427 h.update(chunk)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
428 return h.hexdigest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
429
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
430 def httpsendfile(ui, filename):
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15206
diff changeset
431 return httpconnection.httpsendfile(ui, filename, 'rb')
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
432
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
433 def unixpath(path):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
434 '''Return a version of path normalized for use with the lfdirstate.'''
16066
6a42846cf769 i18n: use util.pconvert() instead of 'str.replace()' for problematic encoding
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15915
diff changeset
435 return util.pconvert(os.path.normpath(path))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
436
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
437 def islfilesrepo(repo):
17659
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
438 if ('largefiles' in repo.requirements and
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
439 util.any(shortname + '/' in f[0] for f in repo.store.datafiles())):
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
440 return True
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
441
ae57920ac188 largefiles: enable islfilesrepo() prior to a commit (issue3541)
Matt Harbison <matt_harbison@yahoo.com>
parents: 17270
diff changeset
442 return util.any(openlfdirstate(repo.ui, repo, False))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
443
15333
f37b71fec602 largefiles: py2.4 doesn't have BaseException
Matt Mackall <mpm@selenic.com>
parents: 15320
diff changeset
444 class storeprotonotcapable(Exception):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
445 def __init__(self, storetypes):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
446 self.storetypes = storetypes
16103
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
447
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
448 def getcurrentheads(repo):
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
449 branches = repo.branchmap()
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
450 heads = []
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
451 for branch in branches:
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
452 newheads = repo.branchheads(branch)
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
453 heads = heads + newheads
3e1efb458e8b largefiles: only cache largefiles in new heads
Na'Tosha Bard <natosha@unity3d.com>
parents: 16066
diff changeset
454 return heads
16120
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
455
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
456 def getstandinsstate(repo):
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
457 standins = []
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
458 matcher = getstandinmatcher(repo)
16247
d87d9d8a8e03 largefiles: remove use of underscores that breaks coding convention
Na'Tosha Bard <natosha@unity3d.com>
parents: 16245
diff changeset
459 for standin in dirstatewalk(repo.dirstate, matcher):
16120
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
460 lfile = splitstandin(standin)
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
461 standins.append((lfile, readstandin(repo, lfile)))
47ee41fcf42b largefiles: optimize update speed by only updating changed largefiles
Na'Tosha Bard <natosha@unity3d.com>
parents: 16103
diff changeset
462 return standins
16245
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
463
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
464 def getlfilestoupdate(oldstandins, newstandins):
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
465 changedstandins = set(oldstandins).symmetric_difference(set(newstandins))
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
466 filelist = []
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
467 for f in changedstandins:
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
468 if f[0] not in filelist:
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
469 filelist.append(f[0])
a18ad914aa21 largefiles: move calculation of largefiles for updating to utility function
Na'Tosha Bard <natosha@unity3d.com>
parents: 16166
diff changeset
470 return filelist