xref: /rk3399_rockchip-uboot/tools/patman/gitutil.py (revision 7f14f30a6d6c80f9fbe3fd8d5b0c294575e3094e)
10d24de9dSSimon Glass# Copyright (c) 2011 The Chromium OS Authors.
20d24de9dSSimon Glass#
30d24de9dSSimon Glass# See file CREDITS for list of people who contributed to this
40d24de9dSSimon Glass# project.
50d24de9dSSimon Glass#
60d24de9dSSimon Glass# This program is free software; you can redistribute it and/or
70d24de9dSSimon Glass# modify it under the terms of the GNU General Public License as
80d24de9dSSimon Glass# published by the Free Software Foundation; either version 2 of
90d24de9dSSimon Glass# the License, or (at your option) any later version.
100d24de9dSSimon Glass#
110d24de9dSSimon Glass# This program is distributed in the hope that it will be useful,
120d24de9dSSimon Glass# but WITHOUT ANY WARRANTY; without even the implied warranty of
130d24de9dSSimon Glass# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
140d24de9dSSimon Glass# GNU General Public License for more details.
150d24de9dSSimon Glass#
160d24de9dSSimon Glass# You should have received a copy of the GNU General Public License
170d24de9dSSimon Glass# along with this program; if not, write to the Free Software
180d24de9dSSimon Glass# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
190d24de9dSSimon Glass# MA 02111-1307 USA
200d24de9dSSimon Glass#
210d24de9dSSimon Glass
220d24de9dSSimon Glassimport command
230d24de9dSSimon Glassimport re
240d24de9dSSimon Glassimport os
250d24de9dSSimon Glassimport series
260d24de9dSSimon Glassimport settings
270d24de9dSSimon Glassimport subprocess
280d24de9dSSimon Glassimport sys
290d24de9dSSimon Glassimport terminal
300d24de9dSSimon Glass
310d24de9dSSimon Glass
320d24de9dSSimon Glassdef CountCommitsToBranch():
330d24de9dSSimon Glass    """Returns number of commits between HEAD and the tracking branch.
340d24de9dSSimon Glass
350d24de9dSSimon Glass    This looks back to the tracking branch and works out the number of commits
360d24de9dSSimon Glass    since then.
370d24de9dSSimon Glass
380d24de9dSSimon Glass    Return:
390d24de9dSSimon Glass        Number of patches that exist on top of the branch
400d24de9dSSimon Glass    """
41*7f14f30aSAlbert ARIBAUD    pipe = [['git', 'log', '--no-color', '--oneline', '@{upstream}..'],
420d24de9dSSimon Glass            ['wc', '-l']]
430d24de9dSSimon Glass    stdout = command.RunPipe(pipe, capture=True, oneline=True)
440d24de9dSSimon Glass    patch_count = int(stdout)
450d24de9dSSimon Glass    return patch_count
460d24de9dSSimon Glass
470d24de9dSSimon Glassdef CreatePatches(start, count, series):
480d24de9dSSimon Glass    """Create a series of patches from the top of the current branch.
490d24de9dSSimon Glass
500d24de9dSSimon Glass    The patch files are written to the current directory using
510d24de9dSSimon Glass    git format-patch.
520d24de9dSSimon Glass
530d24de9dSSimon Glass    Args:
540d24de9dSSimon Glass        start: Commit to start from: 0=HEAD, 1=next one, etc.
550d24de9dSSimon Glass        count: number of commits to include
560d24de9dSSimon Glass    Return:
570d24de9dSSimon Glass        Filename of cover letter
580d24de9dSSimon Glass        List of filenames of patch files
590d24de9dSSimon Glass    """
600d24de9dSSimon Glass    if series.get('version'):
610d24de9dSSimon Glass        version = '%s ' % series['version']
620d24de9dSSimon Glass    cmd = ['git', 'format-patch', '-M', '--signoff']
630d24de9dSSimon Glass    if series.get('cover'):
640d24de9dSSimon Glass        cmd.append('--cover-letter')
650d24de9dSSimon Glass    prefix = series.GetPatchPrefix()
660d24de9dSSimon Glass    if prefix:
670d24de9dSSimon Glass        cmd += ['--subject-prefix=%s' % prefix]
680d24de9dSSimon Glass    cmd += ['HEAD~%d..HEAD~%d' % (start + count, start)]
690d24de9dSSimon Glass
700d24de9dSSimon Glass    stdout = command.RunList(cmd)
710d24de9dSSimon Glass    files = stdout.splitlines()
720d24de9dSSimon Glass
730d24de9dSSimon Glass    # We have an extra file if there is a cover letter
740d24de9dSSimon Glass    if series.get('cover'):
750d24de9dSSimon Glass       return files[0], files[1:]
760d24de9dSSimon Glass    else:
770d24de9dSSimon Glass       return None, files
780d24de9dSSimon Glass
790d24de9dSSimon Glassdef ApplyPatch(verbose, fname):
800d24de9dSSimon Glass    """Apply a patch with git am to test it
810d24de9dSSimon Glass
820d24de9dSSimon Glass    TODO: Convert these to use command, with stderr option
830d24de9dSSimon Glass
840d24de9dSSimon Glass    Args:
850d24de9dSSimon Glass        fname: filename of patch file to apply
860d24de9dSSimon Glass    """
870d24de9dSSimon Glass    cmd = ['git', 'am', fname]
880d24de9dSSimon Glass    pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
890d24de9dSSimon Glass            stderr=subprocess.PIPE)
900d24de9dSSimon Glass    stdout, stderr = pipe.communicate()
910d24de9dSSimon Glass    re_error = re.compile('^error: patch failed: (.+):(\d+)')
920d24de9dSSimon Glass    for line in stderr.splitlines():
930d24de9dSSimon Glass        if verbose:
940d24de9dSSimon Glass            print line
950d24de9dSSimon Glass        match = re_error.match(line)
960d24de9dSSimon Glass        if match:
970d24de9dSSimon Glass            print GetWarningMsg('warning', match.group(1), int(match.group(2)),
980d24de9dSSimon Glass                    'Patch failed')
990d24de9dSSimon Glass    return pipe.returncode == 0, stdout
1000d24de9dSSimon Glass
1010d24de9dSSimon Glassdef ApplyPatches(verbose, args, start_point):
1020d24de9dSSimon Glass    """Apply the patches with git am to make sure all is well
1030d24de9dSSimon Glass
1040d24de9dSSimon Glass    Args:
1050d24de9dSSimon Glass        verbose: Print out 'git am' output verbatim
1060d24de9dSSimon Glass        args: List of patch files to apply
1070d24de9dSSimon Glass        start_point: Number of commits back from HEAD to start applying.
1080d24de9dSSimon Glass            Normally this is len(args), but it can be larger if a start
1090d24de9dSSimon Glass            offset was given.
1100d24de9dSSimon Glass    """
1110d24de9dSSimon Glass    error_count = 0
1120d24de9dSSimon Glass    col = terminal.Color()
1130d24de9dSSimon Glass
1140d24de9dSSimon Glass    # Figure out our current position
1150d24de9dSSimon Glass    cmd = ['git', 'name-rev', 'HEAD', '--name-only']
1160d24de9dSSimon Glass    pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE)
1170d24de9dSSimon Glass    stdout, stderr = pipe.communicate()
1180d24de9dSSimon Glass    if pipe.returncode:
1190d24de9dSSimon Glass        str = 'Could not find current commit name'
1200d24de9dSSimon Glass        print col.Color(col.RED, str)
1210d24de9dSSimon Glass        print stdout
1220d24de9dSSimon Glass        return False
1230d24de9dSSimon Glass    old_head = stdout.splitlines()[0]
1240d24de9dSSimon Glass
1250d24de9dSSimon Glass    # Checkout the required start point
1260d24de9dSSimon Glass    cmd = ['git', 'checkout', 'HEAD~%d' % start_point]
1270d24de9dSSimon Glass    pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
1280d24de9dSSimon Glass            stderr=subprocess.PIPE)
1290d24de9dSSimon Glass    stdout, stderr = pipe.communicate()
1300d24de9dSSimon Glass    if pipe.returncode:
1310d24de9dSSimon Glass        str = 'Could not move to commit before patch series'
1320d24de9dSSimon Glass        print col.Color(col.RED, str)
1330d24de9dSSimon Glass        print stdout, stderr
1340d24de9dSSimon Glass        return False
1350d24de9dSSimon Glass
1360d24de9dSSimon Glass    # Apply all the patches
1370d24de9dSSimon Glass    for fname in args:
1380d24de9dSSimon Glass        ok, stdout = ApplyPatch(verbose, fname)
1390d24de9dSSimon Glass        if not ok:
1400d24de9dSSimon Glass            print col.Color(col.RED, 'git am returned errors for %s: will '
1410d24de9dSSimon Glass                    'skip this patch' % fname)
1420d24de9dSSimon Glass            if verbose:
1430d24de9dSSimon Glass                print stdout
1440d24de9dSSimon Glass            error_count += 1
1450d24de9dSSimon Glass            cmd = ['git', 'am', '--skip']
1460d24de9dSSimon Glass            pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE)
1470d24de9dSSimon Glass            stdout, stderr = pipe.communicate()
1480d24de9dSSimon Glass            if pipe.returncode != 0:
1490d24de9dSSimon Glass                print col.Color(col.RED, 'Unable to skip patch! Aborting...')
1500d24de9dSSimon Glass                print stdout
1510d24de9dSSimon Glass                break
1520d24de9dSSimon Glass
1530d24de9dSSimon Glass    # Return to our previous position
1540d24de9dSSimon Glass    cmd = ['git', 'checkout', old_head]
1550d24de9dSSimon Glass    pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1560d24de9dSSimon Glass    stdout, stderr = pipe.communicate()
1570d24de9dSSimon Glass    if pipe.returncode:
1580d24de9dSSimon Glass        print col.Color(col.RED, 'Could not move back to head commit')
1590d24de9dSSimon Glass        print stdout, stderr
1600d24de9dSSimon Glass    return error_count == 0
1610d24de9dSSimon Glass
1620d24de9dSSimon Glassdef BuildEmailList(in_list, tag=None, alias=None):
1630d24de9dSSimon Glass    """Build a list of email addresses based on an input list.
1640d24de9dSSimon Glass
1650d24de9dSSimon Glass    Takes a list of email addresses and aliases, and turns this into a list
1660d24de9dSSimon Glass    of only email address, by resolving any aliases that are present.
1670d24de9dSSimon Glass
1680d24de9dSSimon Glass    If the tag is given, then each email address is prepended with this
1690d24de9dSSimon Glass    tag and a space. If the tag starts with a minus sign (indicating a
1700d24de9dSSimon Glass    command line parameter) then the email address is quoted.
1710d24de9dSSimon Glass
1720d24de9dSSimon Glass    Args:
1730d24de9dSSimon Glass        in_list:        List of aliases/email addresses
1740d24de9dSSimon Glass        tag:            Text to put before each address
1750d24de9dSSimon Glass
1760d24de9dSSimon Glass    Returns:
1770d24de9dSSimon Glass        List of email addresses
1780d24de9dSSimon Glass
1790d24de9dSSimon Glass    >>> alias = {}
1800d24de9dSSimon Glass    >>> alias['fred'] = ['f.bloggs@napier.co.nz']
1810d24de9dSSimon Glass    >>> alias['john'] = ['j.bloggs@napier.co.nz']
1820d24de9dSSimon Glass    >>> alias['mary'] = ['Mary Poppins <m.poppins@cloud.net>']
1830d24de9dSSimon Glass    >>> alias['boys'] = ['fred', ' john']
1840d24de9dSSimon Glass    >>> alias['all'] = ['fred ', 'john', '   mary   ']
1850d24de9dSSimon Glass    >>> BuildEmailList(['john', 'mary'], None, alias)
1860d24de9dSSimon Glass    ['j.bloggs@napier.co.nz', 'Mary Poppins <m.poppins@cloud.net>']
1870d24de9dSSimon Glass    >>> BuildEmailList(['john', 'mary'], '--to', alias)
1880d24de9dSSimon Glass    ['--to "j.bloggs@napier.co.nz"', \
1890d24de9dSSimon Glass'--to "Mary Poppins <m.poppins@cloud.net>"']
1900d24de9dSSimon Glass    >>> BuildEmailList(['john', 'mary'], 'Cc', alias)
1910d24de9dSSimon Glass    ['Cc j.bloggs@napier.co.nz', 'Cc Mary Poppins <m.poppins@cloud.net>']
1920d24de9dSSimon Glass    """
1930d24de9dSSimon Glass    quote = '"' if tag and tag[0] == '-' else ''
1940d24de9dSSimon Glass    raw = []
1950d24de9dSSimon Glass    for item in in_list:
1960d24de9dSSimon Glass        raw += LookupEmail(item, alias)
1970d24de9dSSimon Glass    result = []
1980d24de9dSSimon Glass    for item in raw:
1990d24de9dSSimon Glass        if not item in result:
2000d24de9dSSimon Glass            result.append(item)
2010d24de9dSSimon Glass    if tag:
2020d24de9dSSimon Glass        return ['%s %s%s%s' % (tag, quote, email, quote) for email in result]
2030d24de9dSSimon Glass    return result
2040d24de9dSSimon Glass
2050d24de9dSSimon Glassdef EmailPatches(series, cover_fname, args, dry_run, cc_fname,
2060d24de9dSSimon Glass        self_only=False, alias=None):
2070d24de9dSSimon Glass    """Email a patch series.
2080d24de9dSSimon Glass
2090d24de9dSSimon Glass    Args:
2100d24de9dSSimon Glass        series: Series object containing destination info
2110d24de9dSSimon Glass        cover_fname: filename of cover letter
2120d24de9dSSimon Glass        args: list of filenames of patch files
2130d24de9dSSimon Glass        dry_run: Just return the command that would be run
2140d24de9dSSimon Glass        cc_fname: Filename of Cc file for per-commit Cc
2150d24de9dSSimon Glass        self_only: True to just email to yourself as a test
2160d24de9dSSimon Glass
2170d24de9dSSimon Glass    Returns:
2180d24de9dSSimon Glass        Git command that was/would be run
2190d24de9dSSimon Glass
2200d24de9dSSimon Glass    >>> alias = {}
2210d24de9dSSimon Glass    >>> alias['fred'] = ['f.bloggs@napier.co.nz']
2220d24de9dSSimon Glass    >>> alias['john'] = ['j.bloggs@napier.co.nz']
2230d24de9dSSimon Glass    >>> alias['mary'] = ['m.poppins@cloud.net']
2240d24de9dSSimon Glass    >>> alias['boys'] = ['fred', ' john']
2250d24de9dSSimon Glass    >>> alias['all'] = ['fred ', 'john', '   mary   ']
2260d24de9dSSimon Glass    >>> alias[os.getenv('USER')] = ['this-is-me@me.com']
2270d24de9dSSimon Glass    >>> series = series.Series()
2280d24de9dSSimon Glass    >>> series.to = ['fred']
2290d24de9dSSimon Glass    >>> series.cc = ['mary']
2300d24de9dSSimon Glass    >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', False, \
2310d24de9dSSimon Glass            alias)
2320d24de9dSSimon Glass    'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
2330d24de9dSSimon Glass"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2'
2340d24de9dSSimon Glass    >>> EmailPatches(series, None, ['p1'], True, 'cc-fname', False, alias)
2350d24de9dSSimon Glass    'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
2360d24de9dSSimon Glass"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" p1'
2370d24de9dSSimon Glass    >>> series.cc = ['all']
2380d24de9dSSimon Glass    >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', True, \
2390d24de9dSSimon Glass            alias)
2400d24de9dSSimon Glass    'git send-email --annotate --to "this-is-me@me.com" --cc-cmd "./patman \
2410d24de9dSSimon Glass--cc-cmd cc-fname" cover p1 p2'
2420d24de9dSSimon Glass    >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', False, \
2430d24de9dSSimon Glass            alias)
2440d24de9dSSimon Glass    'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \
2450d24de9dSSimon Glass"f.bloggs@napier.co.nz" --cc "j.bloggs@napier.co.nz" --cc \
2460d24de9dSSimon Glass"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2'
2470d24de9dSSimon Glass    """
2480d24de9dSSimon Glass    to = BuildEmailList(series.get('to'), '--to', alias)
2490d24de9dSSimon Glass    if not to:
2500d24de9dSSimon Glass        print ("No recipient, please add something like this to a commit\n"
2510d24de9dSSimon Glass            "Series-to: Fred Bloggs <f.blogs@napier.co.nz>")
2520d24de9dSSimon Glass        return
2530d24de9dSSimon Glass    cc = BuildEmailList(series.get('cc'), '--cc', alias)
2540d24de9dSSimon Glass    if self_only:
2550d24de9dSSimon Glass        to = BuildEmailList([os.getenv('USER')], '--to', alias)
2560d24de9dSSimon Glass        cc = []
2570d24de9dSSimon Glass    cmd = ['git', 'send-email', '--annotate']
2580d24de9dSSimon Glass    cmd += to
2590d24de9dSSimon Glass    cmd += cc
2600d24de9dSSimon Glass    cmd += ['--cc-cmd', '"%s --cc-cmd %s"' % (sys.argv[0], cc_fname)]
2610d24de9dSSimon Glass    if cover_fname:
2620d24de9dSSimon Glass        cmd.append(cover_fname)
2630d24de9dSSimon Glass    cmd += args
2640d24de9dSSimon Glass    str = ' '.join(cmd)
2650d24de9dSSimon Glass    if not dry_run:
2660d24de9dSSimon Glass        os.system(str)
2670d24de9dSSimon Glass    return str
2680d24de9dSSimon Glass
2690d24de9dSSimon Glass
2700d24de9dSSimon Glassdef LookupEmail(lookup_name, alias=None, level=0):
2710d24de9dSSimon Glass    """If an email address is an alias, look it up and return the full name
2720d24de9dSSimon Glass
2730d24de9dSSimon Glass    TODO: Why not just use git's own alias feature?
2740d24de9dSSimon Glass
2750d24de9dSSimon Glass    Args:
2760d24de9dSSimon Glass        lookup_name: Alias or email address to look up
2770d24de9dSSimon Glass
2780d24de9dSSimon Glass    Returns:
2790d24de9dSSimon Glass        tuple:
2800d24de9dSSimon Glass            list containing a list of email addresses
2810d24de9dSSimon Glass
2820d24de9dSSimon Glass    Raises:
2830d24de9dSSimon Glass        OSError if a recursive alias reference was found
2840d24de9dSSimon Glass        ValueError if an alias was not found
2850d24de9dSSimon Glass
2860d24de9dSSimon Glass    >>> alias = {}
2870d24de9dSSimon Glass    >>> alias['fred'] = ['f.bloggs@napier.co.nz']
2880d24de9dSSimon Glass    >>> alias['john'] = ['j.bloggs@napier.co.nz']
2890d24de9dSSimon Glass    >>> alias['mary'] = ['m.poppins@cloud.net']
2900d24de9dSSimon Glass    >>> alias['boys'] = ['fred', ' john', 'f.bloggs@napier.co.nz']
2910d24de9dSSimon Glass    >>> alias['all'] = ['fred ', 'john', '   mary   ']
2920d24de9dSSimon Glass    >>> alias['loop'] = ['other', 'john', '   mary   ']
2930d24de9dSSimon Glass    >>> alias['other'] = ['loop', 'john', '   mary   ']
2940d24de9dSSimon Glass    >>> LookupEmail('mary', alias)
2950d24de9dSSimon Glass    ['m.poppins@cloud.net']
2960d24de9dSSimon Glass    >>> LookupEmail('arthur.wellesley@howe.ro.uk', alias)
2970d24de9dSSimon Glass    ['arthur.wellesley@howe.ro.uk']
2980d24de9dSSimon Glass    >>> LookupEmail('boys', alias)
2990d24de9dSSimon Glass    ['f.bloggs@napier.co.nz', 'j.bloggs@napier.co.nz']
3000d24de9dSSimon Glass    >>> LookupEmail('all', alias)
3010d24de9dSSimon Glass    ['f.bloggs@napier.co.nz', 'j.bloggs@napier.co.nz', 'm.poppins@cloud.net']
3020d24de9dSSimon Glass    >>> LookupEmail('odd', alias)
3030d24de9dSSimon Glass    Traceback (most recent call last):
3040d24de9dSSimon Glass    ...
3050d24de9dSSimon Glass    ValueError: Alias 'odd' not found
3060d24de9dSSimon Glass    >>> LookupEmail('loop', alias)
3070d24de9dSSimon Glass    Traceback (most recent call last):
3080d24de9dSSimon Glass    ...
3090d24de9dSSimon Glass    OSError: Recursive email alias at 'other'
3100d24de9dSSimon Glass    """
3110d24de9dSSimon Glass    if not alias:
3120d24de9dSSimon Glass        alias = settings.alias
3130d24de9dSSimon Glass    lookup_name = lookup_name.strip()
3140d24de9dSSimon Glass    if '@' in lookup_name: # Perhaps a real email address
3150d24de9dSSimon Glass        return [lookup_name]
3160d24de9dSSimon Glass
3170d24de9dSSimon Glass    lookup_name = lookup_name.lower()
3180d24de9dSSimon Glass
3190d24de9dSSimon Glass    if level > 10:
3200d24de9dSSimon Glass        raise OSError, "Recursive email alias at '%s'" % lookup_name
3210d24de9dSSimon Glass
3220d24de9dSSimon Glass    out_list = []
3230d24de9dSSimon Glass    if lookup_name:
3240d24de9dSSimon Glass        if not lookup_name in alias:
3250d24de9dSSimon Glass            raise ValueError, "Alias '%s' not found" % lookup_name
3260d24de9dSSimon Glass        for item in alias[lookup_name]:
3270d24de9dSSimon Glass            todo = LookupEmail(item, alias, level + 1)
3280d24de9dSSimon Glass            for new_item in todo:
3290d24de9dSSimon Glass                if not new_item in out_list:
3300d24de9dSSimon Glass                    out_list.append(new_item)
3310d24de9dSSimon Glass
3320d24de9dSSimon Glass    #print "No match for alias '%s'" % lookup_name
3330d24de9dSSimon Glass    return out_list
3340d24de9dSSimon Glass
3350d24de9dSSimon Glassdef GetTopLevel():
3360d24de9dSSimon Glass    """Return name of top-level directory for this git repo.
3370d24de9dSSimon Glass
3380d24de9dSSimon Glass    Returns:
3390d24de9dSSimon Glass        Full path to git top-level directory
3400d24de9dSSimon Glass
3410d24de9dSSimon Glass    This test makes sure that we are running tests in the right subdir
3420d24de9dSSimon Glass
3430d24de9dSSimon Glass    >>> os.path.realpath(os.getcwd()) == \
3440d24de9dSSimon Glass            os.path.join(GetTopLevel(), 'tools', 'scripts', 'patman')
3450d24de9dSSimon Glass    True
3460d24de9dSSimon Glass    """
3470d24de9dSSimon Glass    return command.OutputOneLine('git', 'rev-parse', '--show-toplevel')
3480d24de9dSSimon Glass
3490d24de9dSSimon Glassdef GetAliasFile():
3500d24de9dSSimon Glass    """Gets the name of the git alias file.
3510d24de9dSSimon Glass
3520d24de9dSSimon Glass    Returns:
3530d24de9dSSimon Glass        Filename of git alias file, or None if none
3540d24de9dSSimon Glass    """
3550d24de9dSSimon Glass    fname = command.OutputOneLine('git', 'config', 'sendemail.aliasesfile')
3560d24de9dSSimon Glass    if fname:
3570d24de9dSSimon Glass        fname = os.path.join(GetTopLevel(), fname.strip())
3580d24de9dSSimon Glass    return fname
3590d24de9dSSimon Glass
36087d65558SVikram Narayanandef GetDefaultUserName():
36187d65558SVikram Narayanan    """Gets the user.name from .gitconfig file.
36287d65558SVikram Narayanan
36387d65558SVikram Narayanan    Returns:
36487d65558SVikram Narayanan        User name found in .gitconfig file, or None if none
36587d65558SVikram Narayanan    """
36687d65558SVikram Narayanan    uname = command.OutputOneLine('git', 'config', '--global', 'user.name')
36787d65558SVikram Narayanan    return uname
36887d65558SVikram Narayanan
36987d65558SVikram Narayanandef GetDefaultUserEmail():
37087d65558SVikram Narayanan    """Gets the user.email from the global .gitconfig file.
37187d65558SVikram Narayanan
37287d65558SVikram Narayanan    Returns:
37387d65558SVikram Narayanan        User's email found in .gitconfig file, or None if none
37487d65558SVikram Narayanan    """
37587d65558SVikram Narayanan    uemail = command.OutputOneLine('git', 'config', '--global', 'user.email')
37687d65558SVikram Narayanan    return uemail
37787d65558SVikram Narayanan
3780d24de9dSSimon Glassdef Setup():
3790d24de9dSSimon Glass    """Set up git utils, by reading the alias files."""
3800d24de9dSSimon Glass    settings.Setup('')
3810d24de9dSSimon Glass
3820d24de9dSSimon Glass    # Check for a git alias file also
3830d24de9dSSimon Glass    alias_fname = GetAliasFile()
3840d24de9dSSimon Glass    if alias_fname:
3850d24de9dSSimon Glass        settings.ReadGitAliases(alias_fname)
3860d24de9dSSimon Glass
3870d24de9dSSimon Glassif __name__ == "__main__":
3880d24de9dSSimon Glass    import doctest
3890d24de9dSSimon Glass
3900d24de9dSSimon Glass    doctest.testmod()
391