[PATCH 1 of 3] cmdutil: add a function to terse the status

Pulkit Goyal 7895pulkit at gmail.com
Sat Jun 17 10:34:59 EDT 2017


> Thanks for working on this!
>
> I wonder if this tersestatus function couldn't be unit-tested (might be
> easier if it didn't need the "repo" argument). I'd make it easier to
> understand its behaviour I think.

Okay in that case, I will need to pass two other arguments for
repo.root and repo.dirstate._ignore as root and ignorefn respectively.
Or you mean to say not using them?
>
> A couple of remarks (mostly style) below.

Thanks for them, I will follow all of them in V2.
>
>> diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
>> --- a/mercurial/cmdutil.py
>> +++ b/mercurial/cmdutil.py
>> @@ -402,6 +402,115 @@
>>
>>      return commit(ui, repo, recordinwlock, pats, opts)
>>
>> +def tersestatus(repo, statlist, status, ignore):
>> +    """
>> +    Returns a list of statuses with directory collapsed if all the files
>> in the
>> +    directory has the same status.
>> +    """
>> +
>> +    def numfiles(dirname):
>> +        """
>> +        Calculates the number of tracked files in a given directory which
>> also
>> +        includes files which were removed or deleted. Considers ignored
>> files
>> +        if ignore argument is True or 'i' is present in status argument.
>> +        """
>> +        if 'i' in status or ignore:
>> +            def match(fname):
>> +                return False
>> +        else:
>> +            match = repo.dirstate._ignore
>> +        lendir = 0
>> +        abspath = repo.root + pycompat.ossep + dirname
>
>
> Could you use os.path.join() ?
>
>> +        for f in os.listdir(abspath):
>> +            if not match(f):
>> +                lendir += 1
>> +        if absentdir.get(dirname):
>> +            lendir += absentdir[dirname]
>
>
> Python nit: `if dict.get(key):` is better written as `if key in dict:`.
> Here, you could also have written `lendir += absentdir.get(dirname, 0)`
> and drop the 'if'.
>
>
>> +        return lendir
>> +
>> +    def absentones(removedfiles, missingfiles):
>> +        """
>> +        Returns a dictionary of directories and number of files which are
>> either
>> +        removed or missing (deleted) in them.
>> +        """
>> +        absentdir = {}
>> +        absentfiles = removedfiles + missingfiles
>> +        while absentfiles:
>> +            f = absentfiles.pop()
>> +            par = os.path.dirname(f)
>> +            if par == '':
>> +                continue
>> +            try:
>> +                absentdir[par] += 1
>> +            except KeyError:
>> +                absentdir[par] = 1
>> +            if par not in removedfiles:
>> +                absentfiles.append(par)
>> +        return absentdir
>> +
>> +    indexes = {'m': 0, 'a': 1, 'r': 2, 'd': 3, 'u': 4, 'i': 5, 'c': 6}
>> +    absentdir = absentones(statlist[2], statlist[3])
>> +    finalrs = [[], [], [], [], [], [], []]
>
>
> is it `finalrs = [[]] * len(indexes)` ?
>
>> +    didsomethingchanged = False
>> +
>> +    for st in pycompat.bytestr(status):
>> +
>> +        try:
>> +            ind = indexes[st]
>> +        except KeyError:
>> +            raise error.Abort("Unable to parse the terse status, use
>> marduic")
>
>
> What's "marduic"?
> Also, is it really an user error? If not an assertion might be better maybe.

I am not sure what a good user error will be. I am changing it to
("'%s' not recognized" % st) in V2.
>
>> +
>> +        sfiles = statlist[ind]
>> +        if not sfiles:
>> +            continue
>> +        pardict = {}
>> +        for a in sfiles:
>> +            par = os.path.dirname(a)
>> +            try:
>> +                pardict[par].append(a)
>> +            except KeyError:
>> +                pardict[par] = [a]
>
>
> Other python nit: `pardict.setdefault(par, []).append(a)` to replace the
> try/except block.
>
>> +
>> +        rs = []
>> +        newls = []
>> +        for par in iter(pardict):
>
>
> iteritems() since you further need the value (pardict[par])
>
>> +            lenpar = numfiles(par)
>> +            if lenpar == len(pardict[par]):
>> +                newls.append(par)
>> +
>> +        if not newls:
>> +            continue
>> +
>> +        while newls:
>> +            newel = newls.pop()
>> +            if newel == '':
>> +                continue
>> +            parn = os.path.dirname(newel)
>> +            pardict[newel] = []
>> +            try:
>> +                pardict[parn].append(newel + pycompat.ossep)
>> +            except KeyError:
>> +                pardict[parn] = [newel + pycompat.ossep]
>
>
> setdefault could be used here as well.
> Also, why the `+ pycompat.ossep`? Might be worth adding a comment.
>
>> +            lenpar = numfiles(parn)
>> +            if lenpar == len(pardict[parn]):
>> +                newls.append(parn)
>> +
>> +        for par, files in pardict.iteritems():
>
>
> iteritems() -> itervalues(), since "par" is not used.
>
>> +            rs.extend(files)
>> +
>> +        finalrs[ind] = rs
>> +        didsomethingchanged = True
>> +
>> +    # If nothing is changed, make sure the order of files is preserved.
>> +    if not didsomethingchanged:
>> +        return statlist
>> +
>> +    for x in xrange(7):
>> +        if not finalrs[x]:
>> +            finalrs[x] = statlist[x]
>
>

> for rs in finalrs:
>   if not rs:
>      rs[:] = statlist[x]

In this case 'x' won't be defined. So can't use this.
>
>> +
>> +    return finalrs
>> +
>>  def findpossible(cmd, table, strict=False):
>>      """
>>      Return cmd -> (aliases, command table entry)
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at mercurial-scm.org
>> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>>
>


More information about the Mercurial-devel mailing list