def cachelfiles(ui, repo, node):
    '''cachelfiles ensures that all largefiles needed by the specified revision
    are present in the repository's largefile cache.

    returns a tuple (cached, missing).  cached is the list of files downloaded
    by this operation; missing is the list of files that were needed but could
    not be found.'''
    lfiles = lfutil.listlfiles(repo, node)
    toget = []

    for lfile in lfiles:
        # If we are mid-merge, then we have to trust the standin that is in the
        # working copy to have the correct hashvalue.  This is because the
        # original hg.merge() already updated the standin as part of the normal
        # merge process -- we just have to udpate the largefile to match.
        if (getattr(repo, "_ismerging", False) and
             os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
            expectedhash = lfutil.readstandin(repo, lfile)
        else:
            expectedhash = repo[node][lfutil.standin(lfile)].data().strip()

        # if it exists and its hash matches, it might have been locally
        # modified before updating and the user chose 'local'.  in this case,
        # it will not be in any store, so don't look for it.
        if ((not os.path.exists(repo.wjoin(lfile)) or
             expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
            not lfutil.findfile(repo, expectedhash)):
            toget.append((lfile, expectedhash))

    if toget:
        store = basestore._openstore(repo)
        ret = store.get(toget)
        return ret

    return ([], [])
Beispiel #2
0
def override_remove(orig, ui, repo, *pats, **opts):
    manifest = repo[None].manifest()
    installnormalfilesmatchfn(manifest)
    orig(ui, repo, *pats, **opts)
    restorematchfn()

    after, force = opts.get('after'), opts.get('force')
    if not pats and not after:
        raise util.Abort(_('no files specified'))
    m = scmutil.match(repo[None], pats, opts)
    try:
        repo.lfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.lfstatus = False
    modified, added, deleted, clean = [[
        f for f in list if lfutil.standin(f) in manifest
    ] for list in [s[0], s[1], s[3], s[6]]]

    def warn(files, reason):
        for f in files:
            ui.warn(
                _('not removing %s: %s (use -f to force removal)\n') %
                (m.rel(f), reason))

    if force:
        remove, forget = modified + deleted + clean, added
    elif after:
        remove, forget = deleted, []
        warn(modified + added + clean, _('file still exists'))
    else:
        remove, forget = deleted + clean, []
        warn(modified, _('file is modified'))
        warn(added, _('file has been marked for add'))

    for f in sorted(remove + forget):
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the
    # repository and we could race inbetween.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        for f in remove:
            if not after:
                os.unlink(repo.wjoin(f))
                currentdir = os.path.split(f)[0]
                while currentdir and not os.listdir(repo.wjoin(currentdir)):
                    os.rmdir(repo.wjoin(currentdir))
                    currentdir = os.path.split(currentdir)[0]
            lfdirstate.remove(f)
        lfdirstate.write()

        forget = [lfutil.standin(f) for f in forget]
        remove = [lfutil.standin(f) for f in remove]
        lfutil.repo_forget(repo, forget)
        lfutil.repo_remove(repo, remove, unlink=True)
    finally:
        wlock.release()
Beispiel #3
0
    def getfilectx(repo, memctx, f):
        if lfutil.standin(f) in files:
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            try:
                fctx = ctx.filectx(lfutil.standin(f))
            except error.LookupError:
                return None
            renamed = fctx.renamed()
            if renamed:
                renamed = lfutil.splitstandin(renamed[0])

            hash = fctx.data().strip()
            path = lfutil.findfile(rsrc, hash)

            # If one file is missing, likely all files from this rev are
            if path is None:
                cachelfiles(ui, rsrc, ctx.node())
                path = lfutil.findfile(rsrc, hash)

                if path is None:
                    raise util.Abort(_("missing largefile '%s' from revision %s") % (f, node.hex(ctx.node())))

            data = ""
            fd = None
            try:
                fd = open(path, "rb")
                data = fd.read()
            finally:
                if fd:
                    fd.close()
            return context.memfilectx(repo, f, data, "l" in fctx.flags(), "x" in fctx.flags(), renamed)
        else:
            return _getnormalcontext(repo, ctx, f, revmap)
Beispiel #4
0
def overrideupdate(orig, ui, repo, *pats, **opts):
    lfdirstate = lfutil.openlfdirstate(ui, repo)
    s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
        False, False)
    (unsure, modified, added, removed, missing, unknown, ignored, clean) = s

    # Need to lock between the standins getting updated and their
    # largefiles getting updated
    wlock = repo.wlock()
    try:
        if opts['check']:
            mod = len(modified) > 0
            for lfile in unsure:
                standin = lfutil.standin(lfile)
                if repo['.'][standin].data().strip() != \
                        lfutil.hashfile(repo.wjoin(lfile)):
                    mod = True
                else:
                    lfdirstate.normal(lfile)
            lfdirstate.write()
            if mod:
                raise util.Abort(_('uncommitted changes'))
        # XXX handle removed differently
        if not opts['clean']:
            for lfile in unsure + modified + added:
                lfutil.updatestandin(repo, lfutil.standin(lfile))
    finally:
        wlock.release()
    return orig(ui, repo, *pats, **opts)
Beispiel #5
0
def cachelfiles(ui, repo, node):
    """cachelfiles ensures that all largefiles needed by the specified revision
    are present in the repository's largefile cache.

    returns a tuple (cached, missing).  cached is the list of files downloaded
    by this operation; missing is the list of files that were needed but could
    not be found."""
    lfiles = lfutil.listlfiles(repo, node)
    toget = []

    for lfile in lfiles:
        # If we are mid-merge, then we have to trust the standin that is in the
        # working copy to have the correct hashvalue.  This is because the
        # original hg.merge() already updated the standin as part of the normal
        # merge process -- we just have to udpate the largefile to match.
        if getattr(repo, "_ismerging", False) and os.path.exists(repo.wjoin(lfutil.standin(lfile))):
            expectedhash = lfutil.readstandin(repo, lfile)
        else:
            expectedhash = repo[node][lfutil.standin(lfile)].data().strip()

        # if it exists and its hash matches, it might have been locally
        # modified before updating and the user chose 'local'.  in this case,
        # it will not be in any store, so don't look for it.
        if (
            not os.path.exists(repo.wjoin(lfile)) or expectedhash != lfutil.hashfile(repo.wjoin(lfile))
        ) and not lfutil.findfile(repo, expectedhash):
            toget.append((lfile, expectedhash))

    if toget:
        store = basestore._openstore(repo)
        ret = store.get(toget)
        return ret

    return ([], [])
Beispiel #6
0
    def getfilectx(repo, memctx, f):
        if lfutil.standin(f) in files:
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            try:
                fctx = ctx.filectx(lfutil.standin(f))
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                renamed = lfutil.splitstandin(renamed[0])

            hash = fctx.data().strip()
            path = lfutil.findfile(rsrc, hash)
            ### TODO: What if the file is not cached?
            data = ""
            fd = None
            try:
                fd = open(path, "rb")
                data = fd.read()
            finally:
                if fd:
                    fd.close()
            return context.memfilectx(f, data, "l" in fctx.flags(), "x" in fctx.flags(), renamed)
        else:
            return _getnormalcontext(repo.ui, ctx, f, revmap)
Beispiel #7
0
def overriderevert(orig, ui, repo, *pats, **opts):
    # Because we put the standins in a bad state (by updating them)
    # and then return them to a correct state we need to lock to
    # prevent others from changing them in their incorrect state.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        (modified, added, removed, missing, unknown, ignored, clean) = \
            lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
        lfdirstate.write()
        for lfile in modified:
            lfutil.updatestandin(repo, lfutil.standin(lfile))
        for lfile in missing:
            if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
                os.unlink(repo.wjoin(lfutil.standin(lfile)))

        oldstandins = lfutil.getstandinsstate(repo)

        def overridematch(ctx,
                          pats=[],
                          opts={},
                          globbed=False,
                          default='relpath'):
            match = oldmatch(ctx, pats, opts, globbed, default)
            m = copy.copy(match)

            def tostandin(f):
                if lfutil.standin(f) in ctx:
                    return lfutil.standin(f)
                elif lfutil.standin(f) in repo[None]:
                    return None
                return f

            m._files = [tostandin(f) for f in m._files]
            m._files = [f for f in m._files if f is not None]
            m._fmap = set(m._files)
            m._always = False
            origmatchfn = m.matchfn

            def matchfn(f):
                if lfutil.isstandin(f):
                    return (origmatchfn(lfutil.splitstandin(f))
                            and (f in repo[None] or f in ctx))
                return origmatchfn(f)

            m.matchfn = matchfn
            return m

        oldmatch = installmatchfn(overridematch)
        try:
            orig(ui, repo, *pats, **opts)
        finally:
            restorematchfn()

        newstandins = lfutil.getstandinsstate(repo)
        filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
        lfcommands.updatelfiles(ui, repo, filelist, printmessage=False)

    finally:
        wlock.release()
    def getfilectx(repo, memctx, f):
        if lfutil.standin(f) in files:
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            try:
                fctx = ctx.filectx(lfutil.standin(f))
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                renamed = lfutil.splitstandin(renamed[0])

            hash = fctx.data().strip()
            path = lfutil.findfile(rsrc, hash)
            ### TODO: What if the file is not cached?
            data = ''
            fd = None
            try:
                fd = open(path, 'rb')
                data = fd.read()
            finally:
                if fd:
                    fd.close()
            return context.memfilectx(f, data, 'l' in fctx.flags(),
                                      'x' in fctx.flags(), renamed)
        else:
            return _getnormalcontext(repo.ui, ctx, f, revmap)
Beispiel #9
0
def override_remove(orig, ui, repo, *pats, **opts):
    manifest = repo[None].manifest()
    installnormalfilesmatchfn(manifest)
    orig(ui, repo, *pats, **opts)
    restorematchfn()

    after, force = opts.get('after'), opts.get('force')
    if not pats and not after:
        raise util.Abort(_('no files specified'))
    m = scmutil.match(repo[None], pats, opts)
    try:
        repo.lfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.lfstatus = False
    modified, added, deleted, clean = [[f for f in list
                                        if lfutil.standin(f) in manifest]
                                       for list in [s[0], s[1], s[3], s[6]]]

    def warn(files, reason):
        for f in files:
            ui.warn(_('not removing %s: %s (use -f to force removal)\n')
                    % (m.rel(f), reason))

    if force:
        remove, forget = modified + deleted + clean, added
    elif after:
        remove, forget = deleted, []
        warn(modified + added + clean, _('file still exists'))
    else:
        remove, forget = deleted + clean, []
        warn(modified, _('file is modified'))
        warn(added, _('file has been marked for add'))

    for f in sorted(remove + forget):
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the
    # repository and we could race inbetween.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        for f in remove:
            if not after:
                os.unlink(repo.wjoin(f))
                currentdir = os.path.split(f)[0]
                while currentdir and not os.listdir(repo.wjoin(currentdir)):
                    os.rmdir(repo.wjoin(currentdir))
                    currentdir = os.path.split(currentdir)[0]
            lfdirstate.remove(f)
        lfdirstate.write()

        forget = [lfutil.standin(f) for f in forget]
        remove = [lfutil.standin(f) for f in remove]
        lfutil.repo_forget(repo, forget)
        lfutil.repo_remove(repo, remove, unlink=True)
    finally:
        wlock.release()
def _updatelfile(repo, lfdirstate, lfile):
    '''updates a single largefile and copies the state of its standin from
    the repository's dirstate to its state in the lfdirstate.

    returns 1 if the file was modified, -1 if the file was removed, 0 if the
    file was unchanged, and None if the needed largefile was missing from the
    cache.'''
    ret = 0
    abslfile = repo.wjoin(lfile)
    absstandin = repo.wjoin(lfutil.standin(lfile))
    if os.path.exists(absstandin):
        if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile):
            shutil.copyfile(abslfile, abslfile + '.orig')
        expecthash = lfutil.readstandin(repo, lfile)
        if (expecthash != '' and
            (not os.path.exists(abslfile) or
             expecthash != lfutil.hashfile(abslfile))):
            if not lfutil.copyfromcache(repo, expecthash, lfile):
                # use normallookup() to allocate entry in largefiles dirstate,
                # because lack of it misleads lfilesrepo.status() into
                # recognition that such cache missing files are REMOVED.
                if lfile not in repo[None]: # not switched to normal file
                    util.unlinkpath(abslfile, ignoremissing=True)
                lfdirstate.normallookup(lfile)
                return None # don't try to set the mode
            else:
                # Synchronize largefile dirstate to the last modified time of
                # the file
                lfdirstate.normal(lfile)
            ret = 1
        mode = os.stat(absstandin).st_mode
        if mode != os.stat(abslfile).st_mode:
            os.chmod(abslfile, mode)
            ret = 1
    else:
        # Remove lfiles for which the standin is deleted, unless the
        # lfile is added to the repository again. This happens when a
        # largefile is converted back to a normal file: the standin
        # disappears, but a new (normal) file appears as the lfile.
        if (os.path.exists(abslfile) and
            repo.dirstate.normalize(lfile) not in repo[None]):
            util.unlinkpath(abslfile)
            ret = -1
    state = repo.dirstate[lfutil.standin(lfile)]
    if state == 'n':
        # When rebasing, we need to synchronize the standin and the largefile,
        # because otherwise the largefile will get reverted.  But for commit's
        # sake, we have to mark the file as unclean.
        if getattr(repo, "_isrebasing", False):
            lfdirstate.normallookup(lfile)
        else:
            lfdirstate.normal(lfile)
    elif state == 'r':
        lfdirstate.remove(lfile)
    elif state == 'a':
        lfdirstate.add(lfile)
    elif state == '?':
        lfdirstate.drop(lfile)
    return ret
def overriderevert(orig, ui, repo, *pats, **opts):
    # Because we put the standins in a bad state (by updating them)
    # and then return them to a correct state we need to lock to
    # prevent others from changing them in their incorrect state.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        (modified, added, removed, missing, unknown, ignored, clean) = \
            lfutil.lfdirstatestatus(lfdirstate, repo, repo['.'].rev())
        lfdirstate.write()
        for lfile in modified:
            lfutil.updatestandin(repo, lfutil.standin(lfile))
        for lfile in missing:
            if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
                os.unlink(repo.wjoin(lfutil.standin(lfile)))

        oldstandins = lfutil.getstandinsstate(repo)

        def overridematch(ctx, pats=[], opts={}, globbed=False,
                default='relpath'):
            match = oldmatch(ctx, pats, opts, globbed, default)
            m = copy.copy(match)
            def tostandin(f):
                if lfutil.standin(f) in ctx:
                    return lfutil.standin(f)
                elif lfutil.standin(f) in repo[None]:
                    return None
                return f
            m._files = [tostandin(f) for f in m._files]
            m._files = [f for f in m._files if f is not None]
            m._fmap = set(m._files)
            m._always = False
            origmatchfn = m.matchfn
            def matchfn(f):
                if lfutil.isstandin(f):
                    return (origmatchfn(lfutil.splitstandin(f)) and
                            (f in repo[None] or f in ctx))
                return origmatchfn(f)
            m.matchfn = matchfn
            return m
        oldmatch = installmatchfn(overridematch)
        try:
            orig(ui, repo, *pats, **opts)
        finally:
            restorematchfn()

        newstandins = lfutil.getstandinsstate(repo)
        filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
        # lfdirstate should be 'normallookup'-ed for updated files,
        # because reverting doesn't touch dirstate for 'normal' files
        # when target revision is explicitly specified: in such case,
        # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
        # of target (standin) file.
        lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
                                normallookup=True)

    finally:
        wlock.release()
Beispiel #12
0
def _updatelfile(repo, lfdirstate, lfile):
    '''updates a single largefile and copies the state of its standin from
    the repository's dirstate to its state in the lfdirstate.

    returns 1 if the file was modified, -1 if the file was removed, 0 if the
    file was unchanged, and None if the needed largefile was missing from the
    cache.'''
    ret = 0
    abslfile = repo.wjoin(lfile)
    absstandin = repo.wjoin(lfutil.standin(lfile))
    if os.path.exists(absstandin):
        if os.path.exists(absstandin + '.orig') and os.path.exists(abslfile):
            shutil.copyfile(abslfile, abslfile + '.orig')
        expecthash = lfutil.readstandin(repo, lfile)
        if (expecthash != '' and (not os.path.exists(abslfile)
                                  or expecthash != lfutil.hashfile(abslfile))):
            if not lfutil.copyfromcache(repo, expecthash, lfile):
                # use normallookup() to allocate entry in largefiles dirstate,
                # because lack of it misleads lfilesrepo.status() into
                # recognition that such cache missing files are REMOVED.
                if lfile not in repo[None]:  # not switched to normal file
                    util.unlinkpath(abslfile, ignoremissing=True)
                lfdirstate.normallookup(lfile)
                return None  # don't try to set the mode
            else:
                # Synchronize largefile dirstate to the last modified time of
                # the file
                lfdirstate.normal(lfile)
            ret = 1
        mode = os.stat(absstandin).st_mode
        if mode != os.stat(abslfile).st_mode:
            os.chmod(abslfile, mode)
            ret = 1
    else:
        # Remove lfiles for which the standin is deleted, unless the
        # lfile is added to the repository again. This happens when a
        # largefile is converted back to a normal file: the standin
        # disappears, but a new (normal) file appears as the lfile.
        if (os.path.exists(abslfile)
                and repo.dirstate.normalize(lfile) not in repo[None]):
            util.unlinkpath(abslfile)
            ret = -1
    state = repo.dirstate[lfutil.standin(lfile)]
    if state == 'n':
        # When rebasing, we need to synchronize the standin and the largefile,
        # because otherwise the largefile will get reverted.  But for commit's
        # sake, we have to mark the file as unclean.
        if getattr(repo, "_isrebasing", False):
            lfdirstate.normallookup(lfile)
        else:
            lfdirstate.normal(lfile)
    elif state == 'r':
        lfdirstate.remove(lfile)
    elif state == 'a':
        lfdirstate.add(lfile)
    elif state == '?':
        lfdirstate.drop(lfile)
    return ret
def remove_largefiles(ui, repo, *pats, **opts):
    after = opts.get('after')
    if not pats and not after:
        raise util.Abort(_('no files specified'))
    m = scmutil.match(repo[None], pats, opts)
    try:
        repo.lfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.lfstatus = False
    manifest = repo[None].manifest()
    modified, added, deleted, clean = [[
        f for f in list if lfutil.standin(f) in manifest
    ] for list in [s[0], s[1], s[3], s[6]]]

    def warn(files, reason):
        for f in files:
            ui.warn(
                _('not removing %s: %s (use forget to undo)\n') %
                (m.rel(f), reason))

    if after:
        remove, forget = deleted, []
        warn(modified + added + clean, _('file still exists'))
    else:
        remove, forget = deleted + clean, []
        warn(modified, _('file is modified'))
        warn(added, _('file has been marked for add'))

    for f in sorted(remove + forget):
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the
    # repository and we could race inbetween.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        for f in remove:
            if not after:
                # If this is being called by addremove, notify the user that we
                # are removing the file.
                if getattr(repo, "_isaddremove", False):
                    ui.status(_('removing %s\n') % f)
                if os.path.exists(repo.wjoin(f)):
                    util.unlinkpath(repo.wjoin(f))
            lfdirstate.remove(f)
        lfdirstate.write()
        forget = [lfutil.standin(f) for f in forget]
        remove = [lfutil.standin(f) for f in remove]
        lfutil.repo_forget(repo, forget)
        # If this is being called by addremove, let the original addremove
        # function handle this.
        if not getattr(repo, "_isaddremove", False):
            lfutil.repo_remove(repo, remove, unlink=True)
    finally:
        wlock.release()
def add_largefiles(ui, repo, *pats, **opts):
    large = opts.pop("large", None)
    lfsize = lfutil.getminsize(ui, lfutil.islfilesrepo(repo), opts.pop("lfsize", None))

    lfmatcher = None
    if lfutil.islfilesrepo(repo):
        lfpats = ui.configlist(lfutil.longname, "patterns", default=[])
        if lfpats:
            lfmatcher = match_.match(repo.root, "", list(lfpats))

    lfnames = []
    m = scmutil.match(repo[None], pats, opts)
    m.bad = lambda x, y: None
    wctx = repo[None]
    for f in repo.walk(m):
        exact = m.exact(f)
        lfile = lfutil.standin(f) in wctx
        nfile = f in wctx
        exists = lfile or nfile

        # Don't warn the user when they attempt to add a normal tracked file.
        # The normal add code will do that for us.
        if exact and exists:
            if lfile:
                ui.warn(_("%s already a largefile\n") % f)
            continue

        if exact or not exists:
            abovemin = lfsize and os.lstat(repo.wjoin(f)).st_size >= lfsize * 1024 * 1024
            if large or abovemin or (lfmatcher and lfmatcher(f)):
                lfnames.append(f)
                if ui.verbose or not exact:
                    ui.status(_("adding %s as a largefile\n") % m.rel(f))

    bad = []
    standins = []

    # Need to lock, otherwise there could be a race condition between
    # when standins are created and added to the repo.
    wlock = repo.wlock()
    try:
        if not opts.get("dry_run"):
            lfdirstate = lfutil.openlfdirstate(ui, repo)
            for f in lfnames:
                standinname = lfutil.standin(f)
                lfutil.writestandin(repo, standinname, hash="", executable=lfutil.getexecutable(repo.wjoin(f)))
                standins.append(standinname)
                if lfdirstate[f] == "r":
                    lfdirstate.normallookup(f)
                else:
                    lfdirstate.add(f)
            lfdirstate.write()
            bad += [lfutil.splitstandin(f) for f in lfutil.repo_add(repo, standins) if f in m.files()]
    finally:
        wlock.release()
    return bad
Beispiel #15
0
def remove_largefiles(ui, repo, *pats, **opts):
    after = opts.get('after')
    if not pats and not after:
        raise util.Abort(_('no files specified'))
    m = scmutil.match(repo[None], pats, opts)
    try:
        repo.lfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.lfstatus = False
    manifest = repo[None].manifest()
    modified, added, deleted, clean = [[f for f in list
                                        if lfutil.standin(f) in manifest]
                                       for list in [s[0], s[1], s[3], s[6]]]

    def warn(files, reason):
        for f in files:
            ui.warn(_('not removing %s: %s (use forget to undo)\n')
                    % (m.rel(f), reason))

    if after:
        remove, forget = deleted, []
        warn(modified + added + clean, _('file still exists'))
    else:
        remove, forget = deleted + clean, []
        warn(modified, _('file is modified'))
        warn(added, _('file has been marked for add'))

    for f in sorted(remove + forget):
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the
    # repository and we could race inbetween.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        for f in remove:
            if not after:
                # If this is being called by addremove, notify the user that we
                # are removing the file.
                if getattr(repo, "_isaddremove", False):
                    ui.status(_('removing %s\n' % f))
                if os.path.exists(repo.wjoin(f)):
                    util.unlinkpath(repo.wjoin(f))
            lfdirstate.remove(f)
        lfdirstate.write()
        forget = [lfutil.standin(f) for f in forget]
        remove = [lfutil.standin(f) for f in remove]
        lfutil.repo_forget(repo, forget)
        # If this is being called by addremove, let the original addremove
        # function handle this.
        if not getattr(repo, "_isaddremove", False):
            lfutil.repo_remove(repo, remove, unlink=True)
    finally:
        wlock.release()
def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
                             partial, acceptremote, followcopies):
    overwrite = force and not branchmerge
    actions = origfn(repo, p1, p2, pas, branchmerge, force, partial,
                     acceptremote, followcopies)

    if overwrite:
        return actions

    removes = set(a[0] for a in actions['r'])

    newglist = []
    for action in actions['g']:
        f, args, msg = action
        splitstandin = f and lfutil.splitstandin(f)
        if (splitstandin is not None and
            splitstandin in p1 and splitstandin not in removes):
            # Case 1: normal file in the working copy, largefile in
            # the second parent
            lfile = splitstandin
            standin = f
            msg = _('remote turned local normal file %s into a largefile\n'
                    'use (l)argefile or keep (n)ormal file?'
                    '$$ &Largefile $$ &Normal file') % lfile
            if repo.ui.promptchoice(msg, 0) == 0:
                actions['r'].append((lfile, None, msg))
                newglist.append((standin, (p2.flags(standin),), msg))
            else:
                actions['r'].append((standin, None, msg))
        elif lfutil.standin(f) in p1 and lfutil.standin(f) not in removes:
            # Case 2: largefile in the working copy, normal file in
            # the second parent
            standin = lfutil.standin(f)
            lfile = f
            msg = _('remote turned local largefile %s into a normal file\n'
                    'keep (l)argefile or use (n)ormal file?'
                    '$$ &Largefile $$ &Normal file') % lfile
            if repo.ui.promptchoice(msg, 0) == 0:
                actions['r'].append((lfile, None, msg))
            else:
                actions['r'].append((standin, None, msg))
                newglist.append((lfile, (p2.flags(lfile),), msg))
        else:
            newglist.append(action)

    newglist.sort()
    actions['g'] = newglist

    return actions
Beispiel #17
0
def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
                             partial, acceptremote, followcopies):
    overwrite = force and not branchmerge
    actions = origfn(repo, p1, p2, pas, branchmerge, force, partial,
                     acceptremote, followcopies)

    if overwrite:
        return actions

    removes = set(a[0] for a in actions if a[1] == 'r')
    processed = []

    for action in actions:
        f, m, args, msg = action

        splitstandin = f and lfutil.splitstandin(f)
        if (m == "g" and splitstandin is not None and splitstandin in p1
                and splitstandin not in removes):
            # Case 1: normal file in the working copy, largefile in
            # the second parent
            lfile = splitstandin
            standin = f
            msg = _('remote turned local normal file %s into a largefile\n'
                    'use (l)argefile or keep (n)ormal file?'
                    '$$ &Largefile $$ &Normal file') % lfile
            if repo.ui.promptchoice(msg, 0) == 0:
                processed.append((lfile, "r", None, msg))
                processed.append((standin, "g", (p2.flags(standin), ), msg))
            else:
                processed.append((standin, "r", None, msg))
        elif (m == "g" and lfutil.standin(f) in p1
              and lfutil.standin(f) not in removes):
            # Case 2: largefile in the working copy, normal file in
            # the second parent
            standin = lfutil.standin(f)
            lfile = f
            msg = _('remote turned local largefile %s into a normal file\n'
                    'keep (l)argefile or use (n)ormal file?'
                    '$$ &Largefile $$ &Normal file') % lfile
            if repo.ui.promptchoice(msg, 0) == 0:
                processed.append((lfile, "r", None, msg))
            else:
                processed.append((standin, "r", None, msg))
                processed.append((lfile, "g", (p2.flags(lfile), ), msg))
        else:
            processed.append(action)

    return processed
Beispiel #18
0
def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
                          partial, acceptremote=False):
    overwrite = force and not branchmerge
    actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
                     acceptremote)

    if overwrite:
        return actions

    removes = set(a[0] for a in actions if a[1] == 'r')
    processed = []

    for action in actions:
        f, m, args, msg = action

        splitstandin = lfutil.splitstandin(f)
        if (m == "g" and splitstandin is not None and
            splitstandin in p1 and splitstandin not in removes):
            # Case 1: normal file in the working copy, largefile in
            # the second parent
            lfile = splitstandin
            standin = f
            msg = _('remote turned local normal file %s into a largefile\n'
                    'use (l)argefile or keep (n)ormal file?'
                    '$$ &Largefile $$ &Normal file') % lfile
            if repo.ui.promptchoice(msg, 0) == 0:
                processed.append((lfile, "r", None, msg))
                processed.append((standin, "g", (p2.flags(standin),), msg))
            else:
                processed.append((standin, "r", None, msg))
        elif (m == "g" and
            lfutil.standin(f) in p1 and lfutil.standin(f) not in removes):
            # Case 2: largefile in the working copy, normal file in
            # the second parent
            standin = lfutil.standin(f)
            lfile = f
            msg = _('remote turned local largefile %s into a normal file\n'
                    'keep (l)argefile or use (n)ormal file?'
                    '$$ &Largefile $$ &Normal file') % lfile
            if repo.ui.promptchoice(msg, 0) == 0:
                processed.append((lfile, "r", None, msg))
            else:
                processed.append((standin, "r", None, msg))
                processed.append((lfile, "g", (p2.flags(lfile),), msg))
        else:
            processed.append(action)

    return processed
Beispiel #19
0
    def overridematch(ctx, pats=[], opts={}, globbed=False, default='relpath'):
        """Matcher that merges root directory with .hglf, suitable for log.
        It is still possible to match .hglf directly.
        For any listed files run log on the standin too.
        matchfn tries both the given filename and with .hglf stripped.
        """
        match = oldmatch(ctx, pats, opts, globbed, default)
        m = copy.copy(match)
        for i in range(0, len(m._files)):
            standin = lfutil.standin(m._files[i])
            if standin in repo[ctx.node()]:
                m._files[i] = standin
        m._fmap = set(m._files)
        m._always = False
        origmatchfn = m.matchfn

        def lfmatchfn(f):
            lf = lfutil.splitstandin(f)
            if lf is not None and origmatchfn(lf):
                return True
            r = origmatchfn(f)
            return r

        m.matchfn = lfmatchfn
        return m
Beispiel #20
0
def cachelfiles(ui, repo, node, filelist=None):
    '''cachelfiles ensures that all largefiles needed by the specified revision
    are present in the repository's largefile cache.

    returns a tuple (cached, missing).  cached is the list of files downloaded
    by this operation; missing is the list of files that were needed but could
    not be found.'''
    lfiles = lfutil.listlfiles(repo, node)
    if filelist:
        lfiles = set(lfiles) & set(filelist)
    toget = []

    for lfile in lfiles:
        try:
            expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
        except IOError as err:
            if err.errno == errno.ENOENT:
                continue # node must be None and standin wasn't found in wctx
            raise
        if not lfutil.findfile(repo, expectedhash):
            toget.append((lfile, expectedhash))

    if toget:
        store = basestore._openstore(repo)
        ret = store.get(toget)
        return ret

    return ([], [])
Beispiel #21
0
 def tostandin(file):
     if working:
         sf = lfutil.standin(file)
         dirstate = repo.dirstate
         if sf in dirstate or sf in dirstate.dirs():
             return sf
     return file
 def tostandin(file):
     if working:
         sf = lfutil.standin(file)
         dirstate = repo.dirstate
         if sf in dirstate or sf in dirstate.dirs():
             return sf
     return file
Beispiel #23
0
def override_checkunknown(origfn, wctx, mctx, folding):
    origunknown = wctx.unknown()
    wctx._unknown = filter(lambda f: lfutil.standin(f) not in wctx, origunknown)
    try:
        return origfn(wctx, mctx, folding)
    finally:
        wctx._unknown = origunknown
Beispiel #24
0
def cachelfiles(ui, repo, node):
    '''cachelfiles ensures that all largefiles needed by the specified revision
    are present in the repository's largefile cache.

    returns a tuple (cached, missing).  cached is the list of files downloaded
    by this operation; missing is the list of files that were needed but could
    not be found.'''
    lfiles = lfutil.listlfiles(repo, node)
    toget = []

    for lfile in lfiles:
        expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
        # if it exists and its hash matches, it might have been locally
        # modified before updating and the user chose 'local'.  in this case,
        # it will not be in any store, so don't look for it.
        if ((not os.path.exists(repo.wjoin(lfile)) or
             expectedhash != lfutil.hashfile(repo.wjoin(lfile))) and
            not lfutil.findfile(repo, expectedhash)):
            toget.append((lfile, expectedhash))

    if toget:
        store = basestore._openstore(repo)
        ret = store.get(toget)
        return ret

    return ([], [])
Beispiel #25
0
 def filectx(self, path, fileid=None, filelog=None):
     try:
         if filelog is not None:
             result = super(lfilesctx, self).filectx(path, fileid, filelog)
         else:
             result = super(lfilesctx, self).filectx(path, fileid)
     except error.LookupError:
         # Adding a null character will cause Mercurial to
         # identify this as a binary file.
         if filelog is not None:
             result = super(lfilesctx, self).filectx(lfutil.standin(path), fileid, filelog)
         else:
             result = super(lfilesctx, self).filectx(lfutil.standin(path), fileid)
         olddata = result.data
         result.data = lambda: olddata() + "\0"
     return result
Beispiel #26
0
def cachelfiles(ui, repo, node, filelist=None):
    '''cachelfiles ensures that all largefiles needed by the specified revision
    are present in the repository's largefile cache.

    returns a tuple (cached, missing).  cached is the list of files downloaded
    by this operation; missing is the list of files that were needed but could
    not be found.'''
    lfiles = lfutil.listlfiles(repo, node)
    if filelist:
        lfiles = set(lfiles) & set(filelist)
    toget = []

    for lfile in lfiles:
        try:
            expectedhash = repo[node][lfutil.standin(lfile)].data().strip()
        except IOError as err:
            if err.errno == errno.ENOENT:
                continue  # node must be None and standin wasn't found in wctx
            raise
        if not lfutil.findfile(repo, expectedhash):
            toget.append((lfile, expectedhash))

    if toget:
        store = basestore._openstore(repo)
        ret = store.get(toget)
        return ret

    return ([], [])
    def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
            default='relpath'):
        """Matcher that merges root directory with .hglf, suitable for log.
        It is still possible to match .hglf directly.
        For any listed files run log on the standin too.
        matchfn tries both the given filename and with .hglf stripped.
        """
        matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
        m, p = copy.copy(matchandpats)

        if m.always():
            # We want to match everything anyway, so there's no benefit trying
            # to add standins.
            return matchandpats

        pats = set(p)
        # TODO: handling of patterns in both cases below
        if m._cwd:
            if os.path.isabs(m._cwd):
                # TODO: handle largefile magic when invoked from other cwd
                return matchandpats
            back = (m._cwd.count('/') + 1) * '../'
            pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
        else:
            pats.update(lfutil.standin(f) for f in p)

        for i in range(0, len(m._files)):
            standin = lfutil.standin(m._files[i])
            if standin in repo[ctx.node()]:
                m._files[i] = standin
            elif m._files[i] not in repo[ctx.node()]:
                m._files.append(standin)
            pats.add(standin)

        m._fmap = set(m._files)
        m._always = False
        origmatchfn = m.matchfn
        def lfmatchfn(f):
            lf = lfutil.splitstandin(f)
            if lf is not None and origmatchfn(lf):
                return True
            r = origmatchfn(f)
            return r
        m.matchfn = lfmatchfn

        return m, pats
def override_checkunknown(origfn, wctx, mctx, folding):
    origunknown = wctx.unknown()
    wctx._unknown = filter(lambda f: lfutil.standin(f) not in wctx,
                           origunknown)
    try:
        return origfn(wctx, mctx, folding)
    finally:
        wctx._unknown = origunknown
def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
                          partial, acceptremote=False):
    overwrite = force and not branchmerge
    actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
                     acceptremote)
    processed = []

    for action in actions:
        if overwrite:
            processed.append(action)
            continue
        f, m, args, msg = action

        choices = (_('&Largefile'), _('&Normal file'))

        splitstandin = lfutil.splitstandin(f)
        if (m == "g" and splitstandin is not None and
            splitstandin in p1 and f in p2):
            # Case 1: normal file in the working copy, largefile in
            # the second parent
            lfile = splitstandin
            standin = f
            msg = _('%s has been turned into a largefile\n'
                    'use (l)argefile or keep as (n)ormal file?') % lfile
            if repo.ui.promptchoice(msg, choices, 0) == 0:
                processed.append((lfile, "r", None, msg))
                processed.append((standin, "g", (p2.flags(standin),), msg))
            else:
                processed.append((standin, "r", None, msg))
        elif m == "g" and lfutil.standin(f) in p1 and f in p2:
            # Case 2: largefile in the working copy, normal file in
            # the second parent
            standin = lfutil.standin(f)
            lfile = f
            msg = _('%s has been turned into a normal file\n'
                    'keep as (l)argefile or use (n)ormal file?') % lfile
            if repo.ui.promptchoice(msg, choices, 0) == 0:
                processed.append((lfile, "r", None, msg))
            else:
                processed.append((standin, "r", None, msg))
                processed.append((lfile, "g", (p2.flags(lfile),), msg))
        else:
            processed.append(action)

    return processed
 def override_match(ctx, pats=[], opts={}, globbed=False, default="relpath"):
     match = oldmatch(ctx, pats, opts, globbed, default)
     m = copy.copy(match)
     notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in manifest)
     m._files = filter(notlfile, m._files)
     m._fmap = set(m._files)
     orig_matchfn = m.matchfn
     m.matchfn = lambda f: notlfile(f) and orig_matchfn(f) or None
     return m
Beispiel #31
0
 def filectx(self, path, fileid=None, filelog=None):
     orig = super(lfilesctx, self).filectx
     try:
         if filelog is not None:
             result = orig(path, fileid, filelog)
         else:
             result = orig(path, fileid)
     except error.LookupError:
         # Adding a null character will cause Mercurial to
         # identify this as a binary file.
         if filelog is not None:
             result = orig(lfutil.standin(path), fileid,
                           filelog)
         else:
             result = orig(lfutil.standin(path), fileid)
         olddata = result.data
         result.data = lambda: olddata() + '\0'
     return result
Beispiel #32
0
def overrideforget(orig, ui, repo, *pats, **opts):
    installnormalfilesmatchfn(repo[None].manifest())
    result = orig(ui, repo, *pats, **opts)
    restorematchfn()
    m = scmutil.match(repo[None], pats, opts)

    try:
        repo.lfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.lfstatus = False
    forget = sorted(s[0] + s[1] + s[3] + s[6])
    forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]

    for f in forget:
        if lfutil.standin(f) not in repo.dirstate and not \
                os.path.isdir(m.rel(lfutil.standin(f))):
            ui.warn(_('not removing %s: file is already untracked\n')
                    % m.rel(f))
            result = 1

    for f in forget:
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the
    # repository and we could race in-between.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        for f in forget:
            if lfdirstate[f] == 'a':
                lfdirstate.drop(f)
            else:
                lfdirstate.remove(f)
        lfdirstate.write()
        standins = [lfutil.standin(f) for f in forget]
        for f in standins:
            util.unlinkpath(repo.wjoin(f), ignoremissing=True)
        repo[None].forget(standins)
    finally:
        wlock.release()

    return result
Beispiel #33
0
    def overridematchandpats(ctx,
                             pats=[],
                             opts={},
                             globbed=False,
                             default='relpath'):
        """Matcher that merges root directory with .hglf, suitable for log.
        It is still possible to match .hglf directly.
        For any listed files run log on the standin too.
        matchfn tries both the given filename and with .hglf stripped.
        """
        matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
        m, p = copy.copy(matchandpats)

        pats = set(p)
        # TODO: handling of patterns in both cases below
        if m._cwd:
            if os.path.isabs(m._cwd):
                # TODO: handle largefile magic when invoked from other cwd
                return matchandpats
            back = (m._cwd.count('/') + 1) * '../'
            pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
        else:
            pats.update(lfutil.standin(f) for f in p)

        for i in range(0, len(m._files)):
            standin = lfutil.standin(m._files[i])
            if standin in repo[ctx.node()]:
                m._files[i] = standin
            pats.add(standin)

        m._fmap = set(m._files)
        m._always = False
        origmatchfn = m.matchfn

        def lfmatchfn(f):
            lf = lfutil.splitstandin(f)
            if lf is not None and origmatchfn(lf):
                return True
            r = origmatchfn(f)
            return r

        m.matchfn = lfmatchfn

        return m, pats
Beispiel #34
0
def overrideforget(orig, ui, repo, *pats, **opts):
    installnormalfilesmatchfn(repo[None].manifest())
    result = orig(ui, repo, *pats, **opts)
    restorematchfn()
    m = scmutil.match(repo[None], pats, opts)

    try:
        repo.lfstatus = True
        s = repo.status(match=m, clean=True)
    finally:
        repo.lfstatus = False
    forget = sorted(s[0] + s[1] + s[3] + s[6])
    forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]

    for f in forget:
        if lfutil.standin(f) not in repo.dirstate and not \
                os.path.isdir(m.rel(lfutil.standin(f))):
            ui.warn(
                _('not removing %s: file is already untracked\n') % m.rel(f))
            result = 1

    for f in forget:
        if ui.verbose or not m.exact(f):
            ui.status(_('removing %s\n') % m.rel(f))

    # Need to lock because standin files are deleted then removed from the
    # repository and we could race in-between.
    wlock = repo.wlock()
    try:
        lfdirstate = lfutil.openlfdirstate(ui, repo)
        for f in forget:
            if lfdirstate[f] == 'a':
                lfdirstate.drop(f)
            else:
                lfdirstate.remove(f)
        lfdirstate.write()
        standins = [lfutil.standin(f) for f in forget]
        for f in standins:
            util.unlinkpath(repo.wjoin(f), ignoremissing=True)
        repo[None].forget(standins)
    finally:
        wlock.release()

    return result
Beispiel #35
0
    def getfilectx(repo, memctx, f):
        if lfutil.standin(f) in files:
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            try:
                fctx = ctx.filectx(lfutil.standin(f))
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                renamed = lfutil.splitstandin(renamed[0])

            hash = fctx.data().strip()
            path = lfutil.findfile(rsrc, hash)
            ### TODO: What if the file is not cached?
            data = ''
            fd = None
            try:
                fd = open(path, 'rb')
                data = fd.read()
            finally:
                if fd:
                    fd.close()
            return context.memfilectx(f, data, 'l' in fctx.flags(),
                                      'x' in fctx.flags(), renamed)
        else:
            try:
                fctx = ctx.filectx(f)
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                renamed = renamed[0]
            data = fctx.data()
            if f == '.hgtags':
                newdata = []
                for line in data.splitlines():
                    id, name = line.split(' ', 1)
                    newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
                        name))
                data = ''.join(newdata)
            return context.memfilectx(f, data, 'l' in fctx.flags(),
                                      'x' in fctx.flags(), renamed)
Beispiel #36
0
 def overridematch(ctx, pats=[], opts={}, globbed=False, default='relpath'):
     match = oldmatch(ctx, pats, opts, globbed, default)
     m = copy.copy(match)
     notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
                               manifest)
     m._files = filter(notlfile, m._files)
     m._fmap = set(m._files)
     m._always = False
     origmatchfn = m.matchfn
     m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
     return m
        def _subdirlfs(self, files, lfiles):
            '''
            Adjust matched file list
            If we pass a directory to commit whose only commitable files
            are largefiles, the core commit code aborts before finding
            the largefiles.
            So we do the following:
            For directories that only have largefiles as matches,
            we explicitly add the largefiles to the match list and remove
            the directory.
            In other cases, we leave the match list unmodified.
            '''
            actualfiles = []
            dirs = []
            regulars = []

            for f in files:
                if lfutil.isstandin(f + '/'):
                    raise util.Abort(
                        _('file "%s" is a largefile standin') % f,
                        hint=('commit the largefile itself instead'))
                # Scan directories
                if os.path.isdir(self.wjoin(f)):
                    dirs.append(f)
                else:
                    regulars.append(f)

            for f in dirs:
                matcheddir = False
                d = self.dirstate.normalize(f) + '/'
                # Check for matched normal files
                for mf in regulars:
                    if self.dirstate.normalize(mf).startswith(d):
                        actualfiles.append(f)
                        matcheddir = True
                        break
                if not matcheddir:
                    # If no normal match, manually append
                    # any matching largefiles
                    for lf in lfiles:
                        if self.dirstate.normalize(lf).startswith(d):
                            actualfiles.append(lf)
                            if not matcheddir:
                                actualfiles.append(lfutil.standin(f))
                                matcheddir = True
                # Nothing in dir, so readd it
                # and let commit reject it
                if not matcheddir:
                    actualfiles.append(f)

            # Always add normal files
            actualfiles += regulars
            return actualfiles
Beispiel #38
0
 def override_match(ctx, pats=[], opts={}, globbed=False,
         default='relpath'):
     newpats = []
     # The patterns were previously mangled to add the standin
     # directory; we need to remove that now
     for pat in pats:
         if match_.patkind(pat) is None and lfutil.shortname in pat:
             newpats.append(pat.replace(lfutil.shortname, ''))
         else:
             newpats.append(pat)
     match = oldmatch(ctx, newpats, opts, globbed, default)
     m = copy.copy(match)
     lfile = lambda f: lfutil.standin(f) in manifest
     m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
     m._fmap = set(m._files)
     orig_matchfn = m.matchfn
     m.matchfn = lambda f: (lfutil.isstandin(f) and
                         lfile(lfutil.splitstandin(f)) and
                         orig_matchfn(lfutil.splitstandin(f)) or
                         None)
     return m
Beispiel #39
0
        def _subdirlfs(self, files, lfiles):
            '''
            Adjust matched file list
            If we pass a directory to commit whose only commitable files
            are largefiles, the core commit code aborts before finding
            the largefiles.
            So we do the following:
            For directories that only have largefiles as matches,
            we explicitly add the largefiles to the match list and remove
            the directory.
            In other cases, we leave the match list unmodified.
            '''
            actualfiles = []
            dirs = []
            regulars = []

            for f in files:
                if lfutil.isstandin(f + '/'):
                    raise util.Abort(
                        _('file "%s" is a largefile standin') % f,
                        hint=('commit the largefile itself instead'))
                # Scan directories
                if os.path.isdir(self.wjoin(f)):
                    dirs.append(f)
                else:
                    regulars.append(f)

            for f in dirs:
                matcheddir = False
                d = self.dirstate.normalize(f) + '/'
                # Check for matched normal files
                for mf in regulars:
                    if self.dirstate.normalize(mf).startswith(d):
                        actualfiles.append(f)
                        matcheddir = True
                        break
                if not matcheddir:
                    # If no normal match, manually append
                    # any matching largefiles
                    for lf in lfiles:
                        if self.dirstate.normalize(lf).startswith(d):
                            actualfiles.append(lf)
                            if not matcheddir:
                                actualfiles.append(lfutil.standin(f))
                                matcheddir = True
                # Nothing in dir, so readd it
                # and let commit reject it
                if not matcheddir:
                    actualfiles.append(f)

            # Always add normal files
            actualfiles += regulars
            return actualfiles
Beispiel #40
0
def override_manifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
    actions = origfn(repo, p1, p2, pa, overwrite, partial)
    processed = []

    for action in actions:
        if overwrite:
            processed.append(action)
            continue
        f, m = action[:2]

        choices = (_('&Largefile'), _('&Normal file'))
        if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
            # Case 1: normal file in the working copy, largefile in
            # the second parent
            lfile = lfutil.splitstandin(f)
            standin = f
            msg = _('%s has been turned into a largefile\n'
                    'use (l)argefile or keep as (n)ormal file?') % lfile
            if repo.ui.promptchoice(msg, choices, 0) == 0:
                processed.append((lfile, "r"))
                processed.append((standin, "g", p2.flags(standin)))
            else:
                processed.append((standin, "r"))
        elif m == "m" and lfutil.standin(f) in p1 and f in p2:
            # Case 2: largefile in the working copy, normal file in
            # the second parent
            standin = lfutil.standin(f)
            lfile = f
            msg = _('%s has been turned into a normal file\n'
                    'keep as (l)argefile or use (n)ormal file?') % lfile
            if repo.ui.promptchoice(msg, choices, 0) == 0:
                processed.append((lfile, "r"))
            else:
                processed.append((standin, "r"))
                processed.append((lfile, "g", p2.flags(lfile)))
        else:
            processed.append(action)

    return processed
def override_manifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
    actions = origfn(repo, p1, p2, pa, overwrite, partial)
    processed = []

    for action in actions:
        if overwrite:
            processed.append(action)
            continue
        f, m = action[:2]

        choices = (_('&Largefile'), _('&Normal file'))
        if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
            # Case 1: normal file in the working copy, largefile in
            # the second parent
            lfile = lfutil.splitstandin(f)
            standin = f
            msg = _('%s has been turned into a largefile\n'
                    'use (l)argefile or keep as (n)ormal file?') % lfile
            if repo.ui.promptchoice(msg, choices, 0) == 0:
                processed.append((lfile, "r"))
                processed.append((standin, "g", p2.flags(standin)))
            else:
                processed.append((standin, "r"))
        elif m == "m" and lfutil.standin(f) in p1 and f in p2:
            # Case 2: largefile in the working copy, normal file in
            # the second parent
            standin = lfutil.standin(f)
            lfile = f
            msg = _('%s has been turned into a normal file\n'
                    'keep as (l)argefile or use (n)ormal file?') % lfile
            if repo.ui.promptchoice(msg, choices, 0) == 0:
                processed.append((lfile, "r"))
            else:
                processed.append((standin, "r"))
                processed.append((lfile, "g", p2.flags(lfile)))
        else:
            processed.append(action)

    return processed
Beispiel #42
0
def _updatelfile(repo, lfdirstate, lfile):
    '''updates a single largefile and copies the state of its standin from
    the repository's dirstate to its state in the lfdirstate.

    returns 1 if the file was modified, -1 if the file was removed, 0 if the
    file was unchanged, and None if the needed largefile was missing from the
    cache.'''
    ret = 0
    abslfile = repo.wjoin(lfile)
    absstandin = repo.wjoin(lfutil.standin(lfile))
    if os.path.exists(absstandin):
        if os.path.exists(absstandin+'.orig'):
            shutil.copyfile(abslfile, abslfile+'.orig')
        expecthash = lfutil.readstandin(repo, lfile)
        if (expecthash != '' and
            (not os.path.exists(abslfile) or
             expecthash != lfutil.hashfile(abslfile))):
            if not lfutil.copyfromcache(repo, expecthash, lfile):
                return None # don't try to set the mode or update the dirstate
            ret = 1
        mode = os.stat(absstandin).st_mode
        if mode != os.stat(abslfile).st_mode:
            os.chmod(abslfile, mode)
            ret = 1
    else:
        if os.path.exists(abslfile):
            os.unlink(abslfile)
            ret = -1
    state = repo.dirstate[lfutil.standin(lfile)]
    if state == 'n':
        lfdirstate.normal(lfile)
    elif state == 'r':
        lfdirstate.remove(lfile)
    elif state == 'a':
        lfdirstate.add(lfile)
    elif state == '?':
        lfdirstate.drop(lfile)
    return ret
Beispiel #43
0
 def override_match(ctx,
                    pats=[],
                    opts={},
                    globbed=False,
                    default='relpath'):
     newpats = []
     # The patterns were previously mangled to add the standin
     # directory; we need to remove that now
     for pat in pats:
         if match_.patkind(pat) is None and lfutil.shortname in pat:
             newpats.append(pat.replace(lfutil.shortname, ''))
         else:
             newpats.append(pat)
     match = oldmatch(ctx, newpats, opts, globbed, default)
     m = copy.copy(match)
     lfile = lambda f: lfutil.standin(f) in manifest
     m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
     m._fmap = set(m._files)
     orig_matchfn = m.matchfn
     m.matchfn = lambda f: (lfutil.isstandin(f) and lfile(
         lfutil.splitstandin(f)) and orig_matchfn(
             lfutil.splitstandin(f)) or None)
     return m
Beispiel #44
0
    def getfilectx(repo, memctx, f):
        if lfutil.standin(f) in files:
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            try:
                fctx = ctx.filectx(lfutil.standin(f))
            except error.LookupError:
                raise IOError
            renamed = fctx.renamed()
            if renamed:
                renamed = lfutil.splitstandin(renamed[0])

            hash = fctx.data().strip()
            path = lfutil.findfile(rsrc, hash)

            # If one file is missing, likely all files from this rev are
            if path is None:
                cachelfiles(ui, rsrc, ctx.node())
                path = lfutil.findfile(rsrc, hash)

                if path is None:
                    raise util.Abort(
                        _("missing largefile \'%s\' from revision %s") %
                        (f, node.hex(ctx.node())))

            data = ''
            fd = None
            try:
                fd = open(path, 'rb')
                data = fd.read()
            finally:
                if fd:
                    fd.close()
            return context.memfilectx(repo, f, data, 'l' in fctx.flags(), 'x'
                                      in fctx.flags(), renamed)
        else:
            return _getnormalcontext(repo, ctx, f, revmap)
 def tostandins(files):
     if not working:
         return files
     newfiles = []
     dirstate = self.dirstate
     for f in files:
         sf = lfutil.standin(f)
         if sf in dirstate:
             newfiles.append(sf)
         elif sf in dirstate.dirs():
             # Directory entries could be regular or
             # standin, check both
             newfiles.extend((f, sf))
         else:
             newfiles.append(f)
     return newfiles
 def tostandins(files):
     if not working:
         return files
     newfiles = []
     dirstate = repo.dirstate
     for f in files:
         sf = lfutil.standin(f)
         if sf in dirstate:
             newfiles.append(sf)
         elif sf in dirstate.dirs():
             # Directory entries could be regular or
             # standin, check both
             newfiles.extend((f, sf))
         else:
             newfiles.append(f)
     return newfiles
    def getfilectx(repo, memctx, f):
        if lfutil.isstandin(f):
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            srcfname = lfutil.splitstandin(f)
            try:
                fctx = ctx.filectx(srcfname)
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                # standin is always a largefile because largefile-ness
                # doesn't change after rename or copy
                renamed = lfutil.standin(renamed[0])

            return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
                fctx.flags(), 'x' in fctx.flags(), renamed)
        else:
            return _getnormalcontext(repo.ui, ctx, f, revmap)
Beispiel #48
0
    def getfilectx(repo, memctx, f):
        if lfutil.isstandin(f):
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            srcfname = lfutil.splitstandin(f)
            try:
                fctx = ctx.filectx(srcfname)
            except error.LookupError:
                raise IOError
            renamed = fctx.renamed()
            if renamed:
                # standin is always a largefile because largefile-ness
                # doesn't change after rename or copy
                renamed = lfutil.standin(renamed[0])

            return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
                fctx.flags(), 'x' in fctx.flags(), renamed)
        else:
            return _getnormalcontext(repo.ui, ctx, f, revmap)
Beispiel #49
0
 def overridematch(ctx, pats=[], opts={}, globbed=False,
         default='relpath'):
     """Matcher that merges root directory with .hglf, suitable for log.
     It is still possible to match .hglf directly.
     For any listed files run log on the standin too.
     matchfn tries both the given filename and with .hglf stripped.
     """
     match = oldmatch(ctx, pats, opts, globbed, default)
     m = copy.copy(match)
     standins = [lfutil.standin(f) for f in m._files]
     m._files.extend(standins)
     m._fmap = set(m._files)
     m._always = False
     origmatchfn = m.matchfn
     def lfmatchfn(f):
         lf = lfutil.splitstandin(f)
         if lf is not None and origmatchfn(lf):
             return True
         r = origmatchfn(f)
         return r
     m.matchfn = lfmatchfn
     return m
Beispiel #50
0
    def getfilectx(repo, memctx, f):
        if lfutil.isstandin(f):
            # if the file isn't in the manifest then it was removed
            # or renamed, raise IOError to indicate this
            srcfname = lfutil.splitstandin(f)
            try:
                fctx = ctx.filectx(srcfname)
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                # standin is always a largefile because largefile-ness
                # doesn't change after rename or copy
                renamed = lfutil.standin(renamed[0])

            return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
                fctx.flags(), 'x' in fctx.flags(), renamed)
        else:
            try:
                fctx = ctx.filectx(f)
            except error.LookupError:
                raise IOError()
            renamed = fctx.renamed()
            if renamed:
                renamed = renamed[0]

            data = fctx.data()
            if f == '.hgtags':
                newdata = []
                for line in data.splitlines():
                    id, name = line.split(' ', 1)
                    newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
                        name))
                data = ''.join(newdata)
            return context.memfilectx(f, data, 'l' in fctx.flags(),
                                      'x' in fctx.flags(), renamed)
        def status(self, node1='.', node2=None, match=None, ignored=False,
                clean=False, unknown=False, listsubrepos=False):
            listignored, listclean, listunknown = ignored, clean, unknown
            if not self.lfstatus:
                return super(lfilesrepo, self).status(node1, node2, match,
                    listignored, listclean, listunknown, listsubrepos)
            else:
                # some calls in this function rely on the old version of status
                self.lfstatus = False
                if isinstance(node1, context.changectx):
                    ctx1 = node1
                else:
                    ctx1 = self[node1]
                if isinstance(node2, context.changectx):
                    ctx2 = node2
                else:
                    ctx2 = self[node2]
                working = ctx2.rev() is None
                parentworking = working and ctx1 == self['.']

                def inctx(file, ctx):
                    try:
                        if ctx.rev() is None:
                            return file in ctx.manifest()
                        ctx[file]
                        return True
                    except KeyError:
                        return False

                if match is None:
                    match = match_.always(self.root, self.getcwd())

                wlock = None
                try:
                    try:
                        # updating the dirstate is optional
                        # so we don't wait on the lock
                        wlock = self.wlock(False)
                    except error.LockError:
                        pass

                    # First check if there were files specified on the
                    # command line.  If there were, and none of them were
                    # largefiles, we should just bail here and let super
                    # handle it -- thus gaining a big performance boost.
                    lfdirstate = lfutil.openlfdirstate(ui, self)
                    if match.files() and not match.anypats():
                        for f in lfdirstate:
                            if match(f):
                                break
                        else:
                            return super(lfilesrepo, self).status(node1, node2,
                                    match, listignored, listclean,
                                    listunknown, listsubrepos)

                    # Create a copy of match that matches standins instead
                    # of largefiles.
                    def tostandins(files):
                        if not working:
                            return files
                        newfiles = []
                        dirstate = self.dirstate
                        for f in files:
                            sf = lfutil.standin(f)
                            if sf in dirstate:
                                newfiles.append(sf)
                            elif sf in dirstate.dirs():
                                # Directory entries could be regular or
                                # standin, check both
                                newfiles.extend((f, sf))
                            else:
                                newfiles.append(f)
                        return newfiles

                    m = copy.copy(match)
                    m._files = tostandins(m._files)

                    result = super(lfilesrepo, self).status(node1, node2, m,
                        ignored, clean, unknown, listsubrepos)
                    if working:

                        def sfindirstate(f):
                            sf = lfutil.standin(f)
                            dirstate = self.dirstate
                            return sf in dirstate or sf in dirstate.dirs()

                        match._files = [f for f in match._files
                                        if sfindirstate(f)]
                        # Don't waste time getting the ignored and unknown
                        # files from lfdirstate
                        s = lfdirstate.status(match, [], False,
                                listclean, False)
                        (unsure, modified, added, removed, missing, _unknown,
                                _ignored, clean) = s
                        if parentworking:
                            for lfile in unsure:
                                standin = lfutil.standin(lfile)
                                if standin not in ctx1:
                                    # from second parent
                                    modified.append(lfile)
                                elif ctx1[standin].data().strip() \
                                        != lfutil.hashfile(self.wjoin(lfile)):
                                    modified.append(lfile)
                                else:
                                    clean.append(lfile)
                                    lfdirstate.normal(lfile)
                        else:
                            tocheck = unsure + modified + added + clean
                            modified, added, clean = [], [], []

                            for lfile in tocheck:
                                standin = lfutil.standin(lfile)
                                if inctx(standin, ctx1):
                                    if ctx1[standin].data().strip() != \
                                            lfutil.hashfile(self.wjoin(lfile)):
                                        modified.append(lfile)
                                    else:
                                        clean.append(lfile)
                                else:
                                    added.append(lfile)

                        # Standins no longer found in lfdirstate has been
                        # removed
                        for standin in ctx1.manifest():
                            if not lfutil.isstandin(standin):
                                continue
                            lfile = lfutil.splitstandin(standin)
                            if not match(lfile):
                                continue
                            if lfile not in lfdirstate:
                                removed.append(lfile)

                        # Filter result lists
                        result = list(result)

                        # Largefiles are not really removed when they're
                        # still in the normal dirstate. Likewise, normal
                        # files are not really removed if they are still in
                        # lfdirstate. This happens in merges where files
                        # change type.
                        removed = [f for f in removed
                                   if f not in self.dirstate]
                        result[2] = [f for f in result[2]
                                     if f not in lfdirstate]

                        lfiles = set(lfdirstate._map)
                        # Unknown files
                        result[4] = set(result[4]).difference(lfiles)
                        # Ignored files
                        result[5] = set(result[5]).difference(lfiles)
                        # combine normal files and largefiles
                        normals = [[fn for fn in filelist
                                    if not lfutil.isstandin(fn)]
                                   for filelist in result]
                        lfiles = (modified, added, removed, missing, [], [],
                                  clean)
                        result = [sorted(list1 + list2)
                                  for (list1, list2) in zip(normals, lfiles)]
                    else:
                        def toname(f):
                            if lfutil.isstandin(f):
                                return lfutil.splitstandin(f)
                            return f
                        result = [[toname(f) for f in items]
                                  for items in result]

                    if wlock:
                        lfdirstate.write()

                finally:
                    if wlock:
                        wlock.release()

                if not listunknown:
                    result[4] = []
                if not listignored:
                    result[5] = []
                if not listclean:
                    result[6] = []
                self.lfstatus = True
                return result