hgext/largefiles/lfcommands.py
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Fri, 11 Nov 2011 02:33:01 +0900
branchstable
changeset 15472 6a7e874390b0
parent 15380 a53888685a6c
child 15579 6c5e6ebe0812
permissions -rw-r--r--
largefiles: treat status of cache missed largefiles as "missing" correctly "hg status" may treat cache missed largefiles as "removed" incorrectly. assumptions for problem case: - there is no cache for largefile "L" - at first, update working directory to the revision in which "L" is not yet added, - then, update working directory to the revision in which "L" is already added and now, "hg status" treats "L" as "removed". current implementation does not allocate entry for cache missed largefile in ".hg/largefiles/dirstate", but files without ".hg/largefiles/dirstate" entry are treated as "removed" by largefiles extension. "hg revert" can not recover from this situation, but "rm -rf .hg/largefiles", because it causes dirstate rebuilding. this patch invokes normallookup() for cache missed largefiles to allocate entry in ".hg/largefiles/dirstate", so "hg status" can treat it as "missing" correctly.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15230
diff changeset
     9
'''High-level command function for lfconvert, plus the cmdtable.'''
15168
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 shutil
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    13
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    14
from mercurial import util, match as match_, hg, node, context, error
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    15
from mercurial.i18n import _
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    16
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    17
import lfutil
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    18
import basestore
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    19
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    20
# -- Commands ----------------------------------------------------------
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    21
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    22
def lfconvert(ui, src, dest, *pats, **opts):
15230
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    23
    '''convert a normal repository to a largefiles repository
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    24
15230
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    25
    Convert repository SOURCE to a new repository DEST, identical to
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    26
    SOURCE except that certain files will be converted as largefiles:
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    27
    specifically, any file that matches any PATTERN *or* whose size is
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    28
    above the minimum size threshold is converted as a largefile. The
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    29
    size used to determine whether or not to track a file as a
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    30
    largefile is the size of the first version of the file. The
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    31
    minimum size can be specified either with --size or in
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    32
    configuration as ``largefiles.size``.
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    33
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    34
    After running this command you will need to make sure that
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    35
    largefiles is enabled anywhere you intend to push the new
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    36
    repository.
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    37
15332
0db47b8d025f largefiles: rename lfconvert --tonormal option to --to-normal
Greg Ward <greg@gerg.ca>
parents: 15317
diff changeset
    38
    Use --to-normal to convert largefiles back to normal files; after
15230
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
    39
    this, the DEST repository can be used without largefiles at all.'''
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    40
15332
0db47b8d025f largefiles: rename lfconvert --tonormal option to --to-normal
Greg Ward <greg@gerg.ca>
parents: 15317
diff changeset
    41
    if opts['to_normal']:
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    42
        tolfile = False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    43
    else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    44
        tolfile = True
15227
a7686abf73a6 largefiles: factor out lfutil.getminsize()
Greg Ward <greg@gerg.ca>
parents: 15224
diff changeset
    45
        size = lfutil.getminsize(ui, True, opts.get('size'), default=None)
15340
0e58513cc59a largefiles: rearrange how lfconvert detects non-local repos
Greg Ward <greg@gerg.ca>
parents: 15339
diff changeset
    46
0e58513cc59a largefiles: rearrange how lfconvert detects non-local repos
Greg Ward <greg@gerg.ca>
parents: 15339
diff changeset
    47
    if not hg.islocal(src):
0e58513cc59a largefiles: rearrange how lfconvert detects non-local repos
Greg Ward <greg@gerg.ca>
parents: 15339
diff changeset
    48
        raise util.Abort(_('%s is not a local Mercurial repo') % src)
0e58513cc59a largefiles: rearrange how lfconvert detects non-local repos
Greg Ward <greg@gerg.ca>
parents: 15339
diff changeset
    49
    if not hg.islocal(dest):
0e58513cc59a largefiles: rearrange how lfconvert detects non-local repos
Greg Ward <greg@gerg.ca>
parents: 15339
diff changeset
    50
        raise util.Abort(_('%s is not a local Mercurial repo') % dest)
0e58513cc59a largefiles: rearrange how lfconvert detects non-local repos
Greg Ward <greg@gerg.ca>
parents: 15339
diff changeset
    51
15339
be1377d19018 largefiles: test lfconvert error handling; remove redundant code
Greg Ward <greg@gerg.ca>
parents: 15332
diff changeset
    52
    rsrc = hg.repository(ui, src)
be1377d19018 largefiles: test lfconvert error handling; remove redundant code
Greg Ward <greg@gerg.ca>
parents: 15332
diff changeset
    53
    ui.status(_('initializing destination %s\n') % dest)
be1377d19018 largefiles: test lfconvert error handling; remove redundant code
Greg Ward <greg@gerg.ca>
parents: 15332
diff changeset
    54
    rdst = hg.repository(ui, dest, create=True)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    55
15171
547da6115d1d largefiles: eliminate naked exceptions
Matt Mackall <mpm@selenic.com>
parents: 15170
diff changeset
    56
    success = False
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    57
    try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    58
        # Lock destination to prevent modification while it is converted to.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    59
        # Don't need to lock src because we are just reading from its history
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    60
        # which can't change.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    61
        dst_lock = rdst.lock()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    62
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    63
        # Get a list of all changesets in the source.  The easy way to do this
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    64
        # is to simply walk the changelog, using changelog.nodesbewteen().
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    65
        # Take a look at mercurial/revlog.py:639 for more details.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    66
        # Use a generator instead of a list to decrease memory usage
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    67
        ctxs = (rsrc[ctx] for ctx in rsrc.changelog.nodesbetween(None,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    68
            rsrc.heads())[0])
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    69
        revmap = {node.nullid: node.nullid}
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    70
        if tolfile:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    71
            lfiles = set()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    72
            normalfiles = set()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    73
            if not pats:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    74
                pats = ui.config(lfutil.longname, 'patterns', default=())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    75
                if pats:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    76
                    pats = pats.split(' ')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    77
            if pats:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    78
                matcher = match_.match(rsrc.root, '', list(pats))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    79
            else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    80
                matcher = None
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    81
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    82
            lfiletohash = {}
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    83
            for ctx in ctxs:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    84
                ui.progress(_('converting revisions'), ctx.rev(),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    85
                    unit=_('revision'), total=rsrc['tip'].rev())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    86
                _lfconvert_addchangeset(rsrc, rdst, ctx, revmap,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    87
                    lfiles, normalfiles, matcher, size, lfiletohash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    88
            ui.progress(_('converting revisions'), None)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    89
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    90
            if os.path.exists(rdst.wjoin(lfutil.shortname)):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    91
                shutil.rmtree(rdst.wjoin(lfutil.shortname))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    92
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    93
            for f in lfiletohash.keys():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    94
                if os.path.isfile(rdst.wjoin(f)):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    95
                    os.unlink(rdst.wjoin(f))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    96
                try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    97
                    os.removedirs(os.path.dirname(rdst.wjoin(f)))
15171
547da6115d1d largefiles: eliminate naked exceptions
Matt Mackall <mpm@selenic.com>
parents: 15170
diff changeset
    98
                except OSError:
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
    99
                    pass
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   100
15303
07811b3b119b largefiles: include 'largefiles' in converted repository requirements
Eli Carter <eli.carter@tektronix.com>
parents: 15255
diff changeset
   101
            # If there were any files converted to largefiles, add largefiles
07811b3b119b largefiles: include 'largefiles' in converted repository requirements
Eli Carter <eli.carter@tektronix.com>
parents: 15255
diff changeset
   102
            # to the destination repository's requirements.
07811b3b119b largefiles: include 'largefiles' in converted repository requirements
Eli Carter <eli.carter@tektronix.com>
parents: 15255
diff changeset
   103
            if lfiles:
07811b3b119b largefiles: include 'largefiles' in converted repository requirements
Eli Carter <eli.carter@tektronix.com>
parents: 15255
diff changeset
   104
                rdst.requirements.add('largefiles')
07811b3b119b largefiles: include 'largefiles' in converted repository requirements
Eli Carter <eli.carter@tektronix.com>
parents: 15255
diff changeset
   105
                rdst._writerequirements()
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   106
        else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   107
            for ctx in ctxs:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   108
                ui.progress(_('converting revisions'), ctx.rev(),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   109
                    unit=_('revision'), total=rsrc['tip'].rev())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   110
                _addchangeset(ui, rsrc, rdst, ctx, revmap)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   111
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   112
            ui.progress(_('converting revisions'), None)
15171
547da6115d1d largefiles: eliminate naked exceptions
Matt Mackall <mpm@selenic.com>
parents: 15170
diff changeset
   113
        success = True
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   114
    finally:
15171
547da6115d1d largefiles: eliminate naked exceptions
Matt Mackall <mpm@selenic.com>
parents: 15170
diff changeset
   115
        if not success:
547da6115d1d largefiles: eliminate naked exceptions
Matt Mackall <mpm@selenic.com>
parents: 15170
diff changeset
   116
            # we failed, remove the new directory
547da6115d1d largefiles: eliminate naked exceptions
Matt Mackall <mpm@selenic.com>
parents: 15170
diff changeset
   117
            shutil.rmtree(rdst.root)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   118
        dst_lock.release()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   119
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   120
def _addchangeset(ui, rsrc, rdst, ctx, revmap):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   121
 # Convert src parents to dst parents
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   122
    parents = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   123
    for p in ctx.parents():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   124
        parents.append(revmap[p.node()])
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   125
    while len(parents) < 2:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   126
        parents.append(node.nullid)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   127
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   128
    # Generate list of changed files
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   129
    files = set(ctx.files())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   130
    if node.nullid not in parents:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   131
        mc = ctx.manifest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   132
        mp1 = ctx.parents()[0].manifest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   133
        mp2 = ctx.parents()[1].manifest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   134
        files |= (set(mp1) | set(mp2)) - set(mc)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   135
        for f in mc:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   136
            if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   137
                files.add(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   138
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   139
    def getfilectx(repo, memctx, f):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   140
        if lfutil.standin(f) in files:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   141
            # if the file isn't in the manifest then it was removed
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   142
            # or renamed, raise IOError to indicate this
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   143
            try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   144
                fctx = ctx.filectx(lfutil.standin(f))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   145
            except error.LookupError:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   146
                raise IOError()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   147
            renamed = fctx.renamed()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   148
            if renamed:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   149
                renamed = lfutil.splitstandin(renamed[0])
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   150
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   151
            hash = fctx.data().strip()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   152
            path = lfutil.findfile(rsrc, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   153
            ### TODO: What if the file is not cached?
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   154
            data = ''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   155
            fd = None
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   156
            try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   157
                fd = open(path, 'rb')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   158
                data = fd.read()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   159
            finally:
15172
fb1dcd2aae2a largefiles: fix multistatement line
Matt Mackall <mpm@selenic.com>
parents: 15171
diff changeset
   160
                if fd:
fb1dcd2aae2a largefiles: fix multistatement line
Matt Mackall <mpm@selenic.com>
parents: 15171
diff changeset
   161
                    fd.close()
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   162
            return context.memfilectx(f, data, 'l' in fctx.flags(),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   163
                                      'x' in fctx.flags(), renamed)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   164
        else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   165
            try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   166
                fctx = ctx.filectx(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   167
            except error.LookupError:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   168
                raise IOError()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   169
            renamed = fctx.renamed()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   170
            if renamed:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   171
                renamed = renamed[0]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   172
            data = fctx.data()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   173
            if f == '.hgtags':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   174
                newdata = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   175
                for line in data.splitlines():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   176
                    id, name = line.split(' ', 1)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   177
                    newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   178
                        name))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   179
                data = ''.join(newdata)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   180
            return context.memfilectx(f, data, 'l' in fctx.flags(),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   181
                                      'x' in fctx.flags(), renamed)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   182
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   183
    dstfiles = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   184
    for file in files:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   185
        if lfutil.isstandin(file):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   186
            dstfiles.append(lfutil.splitstandin(file))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   187
        else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   188
            dstfiles.append(file)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   189
    # Commit
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   190
    mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   191
                          getfilectx, ctx.user(), ctx.date(), ctx.extra())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   192
    ret = rdst.commitctx(mctx)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   193
    rdst.dirstate.setparents(ret)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   194
    revmap[ctx.node()] = rdst.changelog.tip()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   195
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   196
def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   197
        matcher, size, lfiletohash):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   198
    # Convert src parents to dst parents
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   199
    parents = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   200
    for p in ctx.parents():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   201
        parents.append(revmap[p.node()])
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   202
    while len(parents) < 2:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   203
        parents.append(node.nullid)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   204
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   205
    # Generate list of changed files
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   206
    files = set(ctx.files())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   207
    if node.nullid not in parents:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   208
        mc = ctx.manifest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   209
        mp1 = ctx.parents()[0].manifest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   210
        mp2 = ctx.parents()[1].manifest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   211
        files |= (set(mp1) | set(mp2)) - set(mc)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   212
        for f in mc:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   213
            if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   214
                files.add(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   215
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   216
    dstfiles = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   217
    for f in files:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   218
        if f not in lfiles and f not in normalfiles:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   219
            islfile = _islfile(f, ctx, matcher, size)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   220
            # If this file was renamed or copied then copy
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   221
            # the lfileness of its predecessor
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   222
            if f in ctx.manifest():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   223
                fctx = ctx.filectx(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   224
                renamed = fctx.renamed()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   225
                renamedlfile = renamed and renamed[0] in lfiles
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   226
                islfile |= renamedlfile
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   227
                if 'l' in fctx.flags():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   228
                    if renamedlfile:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   229
                        raise util.Abort(
15380
a53888685a6c largefiles: fix uppercase in abort message
Martin Geisler <mg@aragost.com>
parents: 15371
diff changeset
   230
                            _('renamed/copied largefile %s becomes symlink')
15170
c1a4a3220711 largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents: 15168
diff changeset
   231
                            % f)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   232
                    islfile = False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   233
            if islfile:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   234
                lfiles.add(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   235
            else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   236
                normalfiles.add(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   237
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   238
        if f in lfiles:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   239
            dstfiles.append(lfutil.standin(f))
15254
dd03d3a9f888 largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
   240
            # largefile in manifest if it has not been removed/renamed
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   241
            if f in ctx.manifest():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   242
                if 'l' in ctx.filectx(f).flags():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   243
                    if renamed and renamed[0] in lfiles:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   244
                        raise util.Abort(_('largefile %s becomes symlink') % f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   245
15254
dd03d3a9f888 largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
   246
                # largefile was modified, update standins
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   247
                fullpath = rdst.wjoin(f)
15371
f26ed4ea46d8 largefiles: remove lfutil.createdir, replace calls with util.makedirs
Hao Lian <hao@fogcreek.com>
parents: 15340
diff changeset
   248
                util.makedirs(os.path.dirname(fullpath))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   249
                m = util.sha1('')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   250
                m.update(ctx[f].data())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   251
                hash = m.hexdigest()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   252
                if f not in lfiletohash or lfiletohash[f] != hash:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   253
                    try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   254
                        fd = open(fullpath, 'wb')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   255
                        fd.write(ctx[f].data())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   256
                    finally:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   257
                        if fd:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   258
                            fd.close()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   259
                    executable = 'x' in ctx[f].flags()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   260
                    os.chmod(fullpath, lfutil.getmode(executable))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   261
                    lfutil.writestandin(rdst, lfutil.standin(f), hash,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   262
                        executable)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   263
                    lfiletohash[f] = hash
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   264
        else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   265
            # normal file
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   266
            dstfiles.append(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   267
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   268
    def getfilectx(repo, memctx, f):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   269
        if lfutil.isstandin(f):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   270
            # if the file isn't in the manifest then it was removed
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   271
            # or renamed, raise IOError to indicate this
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   272
            srcfname = lfutil.splitstandin(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   273
            try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   274
                fctx = ctx.filectx(srcfname)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   275
            except error.LookupError:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   276
                raise IOError()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   277
            renamed = fctx.renamed()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   278
            if renamed:
15254
dd03d3a9f888 largefiles: more work on cleaning up comments
Greg Ward <greg@gerg.ca>
parents: 15253
diff changeset
   279
                # standin is always a largefile because largefile-ness
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   280
                # doesn't change after rename or copy
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   281
                renamed = lfutil.standin(renamed[0])
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   282
15313
3eb1a90ea409 largefiles: fix newline for lfconverted repos
Eli Carter <eli.carter@tektronix.com>
parents: 15303
diff changeset
   283
            return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   284
                fctx.flags(), 'x' in fctx.flags(), renamed)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   285
        else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   286
            try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   287
                fctx = ctx.filectx(f)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   288
            except error.LookupError:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   289
                raise IOError()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   290
            renamed = fctx.renamed()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   291
            if renamed:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   292
                renamed = renamed[0]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   293
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   294
            data = fctx.data()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   295
            if f == '.hgtags':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   296
                newdata = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   297
                for line in data.splitlines():
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   298
                    id, name = line.split(' ', 1)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   299
                    newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   300
                        name))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   301
                data = ''.join(newdata)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   302
            return context.memfilectx(f, data, 'l' in fctx.flags(),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   303
                                      'x' in fctx.flags(), renamed)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   304
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   305
    # Commit
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   306
    mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   307
                          getfilectx, ctx.user(), ctx.date(), ctx.extra())
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   308
    ret = rdst.commitctx(mctx)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   309
    rdst.dirstate.setparents(ret)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   310
    revmap[ctx.node()] = rdst.changelog.tip()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   311
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   312
def _islfile(file, ctx, matcher, size):
15252
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15230
diff changeset
   313
    '''Return true if file should be considered a largefile, i.e.
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15230
diff changeset
   314
    matcher matches it or it is larger than size.'''
6e809bb4f969 largefiles: improve comments, internal docstrings
Greg Ward <greg@gerg.ca>
parents: 15230
diff changeset
   315
    # never store special .hg* files as largefiles
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   316
    if file == '.hgtags' or file == '.hgignore' or file == '.hgsigs':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   317
        return False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   318
    if matcher and matcher(file):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   319
        return True
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   320
    try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   321
        return ctx.filectx(file).size() >= size * 1024 * 1024
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   322
    except error.LookupError:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   323
        return False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   324
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   325
def uploadlfiles(ui, rsrc, rdst, files):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   326
    '''upload largefiles to the central store'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   327
15317
41f371150ccb largefiles: make the store primary, and the user cache secondary
Benjamin Pollack <benjamin@bitquabit.com>
parents: 15313
diff changeset
   328
    if not files:
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   329
        return
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   330
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   331
    store = basestore._openstore(rsrc, rdst, put=True)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   332
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   333
    at = 0
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   334
    files = filter(lambda h: not store.exists(h), files)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   335
    for hash in files:
15170
c1a4a3220711 largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents: 15168
diff changeset
   336
        ui.progress(_('uploading largefiles'), at, unit='largefile',
c1a4a3220711 largefiles: fix over-long lines
Matt Mackall <mpm@selenic.com>
parents: 15168
diff changeset
   337
                    total=len(files))
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   338
        source = lfutil.findfile(rsrc, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   339
        if not source:
15253
67d010779907 largefiles: improve error reporting
Greg Ward <greg@gerg.ca>
parents: 15252
diff changeset
   340
            raise util.Abort(_('largefile %s missing from store'
67d010779907 largefiles: improve error reporting
Greg Ward <greg@gerg.ca>
parents: 15252
diff changeset
   341
                               ' (needs to be uploaded)') % hash)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   342
        # XXX check for errors here
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   343
        store.put(source, hash)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   344
        at += 1
15173
3d27a8ff895f largefiles: mark a string for translation
Matt Mackall <mpm@selenic.com>
parents: 15172
diff changeset
   345
    ui.progress(_('uploading largefiles'), None)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   346
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   347
def verifylfiles(ui, repo, all=False, contents=False):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   348
    '''Verify that every big file revision in the current changeset
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   349
    exists in the central store.  With --contents, also verify that
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   350
    the contents of each big file revision are correct (SHA-1 hash
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   351
    matches the revision ID).  With --all, check every changeset in
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   352
    this repository.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   353
    if all:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   354
        # Pass a list to the function rather than an iterator because we know a
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   355
        # list will work.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   356
        revs = range(len(repo))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   357
    else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   358
        revs = ['.']
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   359
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   360
    store = basestore._openstore(repo)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   361
    return store.verify(revs, contents=contents)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   362
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   363
def cachelfiles(ui, repo, node):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   364
    '''cachelfiles ensures that all largefiles needed by the specified revision
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   365
    are present in the repository's largefile cache.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   366
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   367
    returns a tuple (cached, missing).  cached is the list of files downloaded
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   368
    by this operation; missing is the list of files that were needed but could
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   369
    not be found.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   370
    lfiles = lfutil.listlfiles(repo, node)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   371
    toget = []
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   372
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   373
    for lfile in lfiles:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   374
        expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   375
        # if it exists and its hash matches, it might have been locally
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   376
        # modified before updating and the user chose 'local'.  in this case,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   377
        # it will not be in any store, so don't look for it.
15255
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15254
diff changeset
   378
        if ((not os.path.exists(repo.wjoin(lfile)) or
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15254
diff changeset
   379
             expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15254
diff changeset
   380
            not lfutil.findfile(repo, expectedhash)):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   381
            toget.append((lfile, expectedhash))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   382
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   383
    if toget:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   384
        store = basestore._openstore(repo)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   385
        ret = store.get(toget)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   386
        return ret
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   387
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   388
    return ([], [])
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   389
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   390
def updatelfiles(ui, repo, filelist=None, printmessage=True):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   391
    wlock = repo.wlock()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   392
    try:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   393
        lfdirstate = lfutil.openlfdirstate(ui, repo)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   394
        lfiles = set(lfutil.listlfiles(repo)) | set(lfdirstate)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   395
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   396
        if filelist is not None:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   397
            lfiles = [f for f in lfiles if f in filelist]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   398
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   399
        printed = False
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   400
        if printmessage and lfiles:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   401
            ui.status(_('getting changed largefiles\n'))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   402
            printed = True
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   403
            cachelfiles(ui, repo, '.')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   404
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   405
        updated, removed = 0, 0
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   406
        for i in map(lambda f: _updatelfile(repo, lfdirstate, f), lfiles):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   407
            # increment the appropriate counter according to _updatelfile's
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   408
            # return value
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   409
            updated += i > 0 and i or 0
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   410
            removed -= i < 0 and i or 0
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   411
            if printmessage and (removed or updated) and not printed:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   412
                ui.status(_('getting changed largefiles\n'))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   413
                printed = True
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   414
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   415
        lfdirstate.write()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   416
        if printed and printmessage:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   417
            ui.status(_('%d largefiles updated, %d removed\n') % (updated,
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   418
                removed))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   419
    finally:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   420
        wlock.release()
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   421
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   422
def _updatelfile(repo, lfdirstate, lfile):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   423
    '''updates a single largefile and copies the state of its standin from
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   424
    the repository's dirstate to its state in the lfdirstate.
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   425
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   426
    returns 1 if the file was modified, -1 if the file was removed, 0 if the
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   427
    file was unchanged, and None if the needed largefile was missing from the
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   428
    cache.'''
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   429
    ret = 0
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   430
    abslfile = repo.wjoin(lfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   431
    absstandin = repo.wjoin(lfutil.standin(lfile))
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   432
    if os.path.exists(absstandin):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   433
        if os.path.exists(absstandin+'.orig'):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   434
            shutil.copyfile(abslfile, abslfile+'.orig')
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   435
        expecthash = lfutil.readstandin(repo, lfile)
15255
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15254
diff changeset
   436
        if (expecthash != '' and
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15254
diff changeset
   437
            (not os.path.exists(abslfile) or
7ab05d752405 largefiles: cosmetics, whitespace, code style
Greg Ward <greg@gerg.ca>
parents: 15254
diff changeset
   438
             expecthash != lfutil.hashfile(abslfile))):
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   439
            if not lfutil.copyfromcache(repo, expecthash, lfile):
15472
6a7e874390b0 largefiles: treat status of cache missed largefiles as "missing" correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15380
diff changeset
   440
                # use normallookup() to allocate entry in largefiles dirstate,
6a7e874390b0 largefiles: treat status of cache missed largefiles as "missing" correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15380
diff changeset
   441
                # because lack of it misleads lfiles_repo.status() into
6a7e874390b0 largefiles: treat status of cache missed largefiles as "missing" correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15380
diff changeset
   442
                # recognition that such cache missing files are REMOVED.
6a7e874390b0 largefiles: treat status of cache missed largefiles as "missing" correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15380
diff changeset
   443
                lfdirstate.normallookup(lfile)
6a7e874390b0 largefiles: treat status of cache missed largefiles as "missing" correctly
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 15380
diff changeset
   444
                return None # don't try to set the mode
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   445
            ret = 1
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   446
        mode = os.stat(absstandin).st_mode
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   447
        if mode != os.stat(abslfile).st_mode:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   448
            os.chmod(abslfile, mode)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   449
            ret = 1
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   450
    else:
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   451
        if os.path.exists(abslfile):
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   452
            os.unlink(abslfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   453
            ret = -1
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   454
    state = repo.dirstate[lfutil.standin(lfile)]
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   455
    if state == 'n':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   456
        lfdirstate.normal(lfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   457
    elif state == 'r':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   458
        lfdirstate.remove(lfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   459
    elif state == 'a':
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   460
        lfdirstate.add(lfile)
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   461
    elif state == '?':
15224
7c604d8c7e83 largefiles: remove pre-1.9 code from extension first bundled with 1.9
Na'Tosha Bard <natosha@unity3d.com>
parents: 15173
diff changeset
   462
        lfdirstate.drop(lfile)
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   463
    return ret
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   464
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   465
# -- hg commands declarations ------------------------------------------------
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   466
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   467
cmdtable = {
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   468
    'lfconvert': (lfconvert,
15230
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
   469
                  [('s', 'size', '',
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
   470
                    _('minimum size (MB) for files to be converted '
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
   471
                      'as largefiles'),
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
   472
                    'SIZE'),
15332
0db47b8d025f largefiles: rename lfconvert --tonormal option to --to-normal
Greg Ward <greg@gerg.ca>
parents: 15317
diff changeset
   473
                  ('', 'to-normal', False,
15230
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
   474
                   _('convert from a largefiles repo to a normal repo')),
697289c5d415 largefiles: improve help
Greg Ward <greg@gerg.ca>
parents: 15228
diff changeset
   475
                  ],
15168
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   476
                  _('hg lfconvert SOURCE DEST [FILE ...]')),
cfccd3bee7b3 hgext: add largefiles extension
various
parents:
diff changeset
   477
    }