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 """ 417f14f30aSAlbert ARIBAUD pipe = [['git', 'log', '--no-color', '--oneline', '@{upstream}..'], 420d24de9dSSimon Glass ['wc', '-l']] 43*a10fd93cSSimon Glass stdout = command.RunPipe(pipe, capture=True, oneline=True).stdout 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 220a970048eSDoug Anderson # For the duration of this doctest pretend that we ran patman with ./patman 221a970048eSDoug Anderson >>> _old_argv0 = sys.argv[0] 222a970048eSDoug Anderson >>> sys.argv[0] = './patman' 223a970048eSDoug Anderson 2240d24de9dSSimon Glass >>> alias = {} 2250d24de9dSSimon Glass >>> alias['fred'] = ['f.bloggs@napier.co.nz'] 2260d24de9dSSimon Glass >>> alias['john'] = ['j.bloggs@napier.co.nz'] 2270d24de9dSSimon Glass >>> alias['mary'] = ['m.poppins@cloud.net'] 2280d24de9dSSimon Glass >>> alias['boys'] = ['fred', ' john'] 2290d24de9dSSimon Glass >>> alias['all'] = ['fred ', 'john', ' mary '] 2300d24de9dSSimon Glass >>> alias[os.getenv('USER')] = ['this-is-me@me.com'] 2310d24de9dSSimon Glass >>> series = series.Series() 2320d24de9dSSimon Glass >>> series.to = ['fred'] 2330d24de9dSSimon Glass >>> series.cc = ['mary'] 2340d24de9dSSimon Glass >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', False, \ 2350d24de9dSSimon Glass alias) 2360d24de9dSSimon Glass 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ 2370d24de9dSSimon Glass"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2' 2380d24de9dSSimon Glass >>> EmailPatches(series, None, ['p1'], True, 'cc-fname', False, alias) 2390d24de9dSSimon Glass 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ 2400d24de9dSSimon Glass"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" p1' 2410d24de9dSSimon Glass >>> series.cc = ['all'] 2420d24de9dSSimon Glass >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', True, \ 2430d24de9dSSimon Glass alias) 2440d24de9dSSimon Glass 'git send-email --annotate --to "this-is-me@me.com" --cc-cmd "./patman \ 2450d24de9dSSimon Glass--cc-cmd cc-fname" cover p1 p2' 2460d24de9dSSimon Glass >>> EmailPatches(series, 'cover', ['p1', 'p2'], True, 'cc-fname', False, \ 2470d24de9dSSimon Glass alias) 2480d24de9dSSimon Glass 'git send-email --annotate --to "f.bloggs@napier.co.nz" --cc \ 2490d24de9dSSimon Glass"f.bloggs@napier.co.nz" --cc "j.bloggs@napier.co.nz" --cc \ 2500d24de9dSSimon Glass"m.poppins@cloud.net" --cc-cmd "./patman --cc-cmd cc-fname" cover p1 p2' 251a970048eSDoug Anderson 252a970048eSDoug Anderson # Restore argv[0] since we clobbered it. 253a970048eSDoug Anderson >>> sys.argv[0] = _old_argv0 2540d24de9dSSimon Glass """ 2550d24de9dSSimon Glass to = BuildEmailList(series.get('to'), '--to', alias) 2560d24de9dSSimon Glass if not to: 2570d24de9dSSimon Glass print ("No recipient, please add something like this to a commit\n" 2580d24de9dSSimon Glass "Series-to: Fred Bloggs <f.blogs@napier.co.nz>") 2590d24de9dSSimon Glass return 2600d24de9dSSimon Glass cc = BuildEmailList(series.get('cc'), '--cc', alias) 2610d24de9dSSimon Glass if self_only: 2620d24de9dSSimon Glass to = BuildEmailList([os.getenv('USER')], '--to', alias) 2630d24de9dSSimon Glass cc = [] 2640d24de9dSSimon Glass cmd = ['git', 'send-email', '--annotate'] 2650d24de9dSSimon Glass cmd += to 2660d24de9dSSimon Glass cmd += cc 2670d24de9dSSimon Glass cmd += ['--cc-cmd', '"%s --cc-cmd %s"' % (sys.argv[0], cc_fname)] 2680d24de9dSSimon Glass if cover_fname: 2690d24de9dSSimon Glass cmd.append(cover_fname) 2700d24de9dSSimon Glass cmd += args 2710d24de9dSSimon Glass str = ' '.join(cmd) 2720d24de9dSSimon Glass if not dry_run: 2730d24de9dSSimon Glass os.system(str) 2740d24de9dSSimon Glass return str 2750d24de9dSSimon Glass 2760d24de9dSSimon Glass 2770d24de9dSSimon Glassdef LookupEmail(lookup_name, alias=None, level=0): 2780d24de9dSSimon Glass """If an email address is an alias, look it up and return the full name 2790d24de9dSSimon Glass 2800d24de9dSSimon Glass TODO: Why not just use git's own alias feature? 2810d24de9dSSimon Glass 2820d24de9dSSimon Glass Args: 2830d24de9dSSimon Glass lookup_name: Alias or email address to look up 2840d24de9dSSimon Glass 2850d24de9dSSimon Glass Returns: 2860d24de9dSSimon Glass tuple: 2870d24de9dSSimon Glass list containing a list of email addresses 2880d24de9dSSimon Glass 2890d24de9dSSimon Glass Raises: 2900d24de9dSSimon Glass OSError if a recursive alias reference was found 2910d24de9dSSimon Glass ValueError if an alias was not found 2920d24de9dSSimon Glass 2930d24de9dSSimon Glass >>> alias = {} 2940d24de9dSSimon Glass >>> alias['fred'] = ['f.bloggs@napier.co.nz'] 2950d24de9dSSimon Glass >>> alias['john'] = ['j.bloggs@napier.co.nz'] 2960d24de9dSSimon Glass >>> alias['mary'] = ['m.poppins@cloud.net'] 2970d24de9dSSimon Glass >>> alias['boys'] = ['fred', ' john', 'f.bloggs@napier.co.nz'] 2980d24de9dSSimon Glass >>> alias['all'] = ['fred ', 'john', ' mary '] 2990d24de9dSSimon Glass >>> alias['loop'] = ['other', 'john', ' mary '] 3000d24de9dSSimon Glass >>> alias['other'] = ['loop', 'john', ' mary '] 3010d24de9dSSimon Glass >>> LookupEmail('mary', alias) 3020d24de9dSSimon Glass ['m.poppins@cloud.net'] 3030d24de9dSSimon Glass >>> LookupEmail('arthur.wellesley@howe.ro.uk', alias) 3040d24de9dSSimon Glass ['arthur.wellesley@howe.ro.uk'] 3050d24de9dSSimon Glass >>> LookupEmail('boys', alias) 3060d24de9dSSimon Glass ['f.bloggs@napier.co.nz', 'j.bloggs@napier.co.nz'] 3070d24de9dSSimon Glass >>> LookupEmail('all', alias) 3080d24de9dSSimon Glass ['f.bloggs@napier.co.nz', 'j.bloggs@napier.co.nz', 'm.poppins@cloud.net'] 3090d24de9dSSimon Glass >>> LookupEmail('odd', alias) 3100d24de9dSSimon Glass Traceback (most recent call last): 3110d24de9dSSimon Glass ... 3120d24de9dSSimon Glass ValueError: Alias 'odd' not found 3130d24de9dSSimon Glass >>> LookupEmail('loop', alias) 3140d24de9dSSimon Glass Traceback (most recent call last): 3150d24de9dSSimon Glass ... 3160d24de9dSSimon Glass OSError: Recursive email alias at 'other' 3170d24de9dSSimon Glass """ 3180d24de9dSSimon Glass if not alias: 3190d24de9dSSimon Glass alias = settings.alias 3200d24de9dSSimon Glass lookup_name = lookup_name.strip() 3210d24de9dSSimon Glass if '@' in lookup_name: # Perhaps a real email address 3220d24de9dSSimon Glass return [lookup_name] 3230d24de9dSSimon Glass 3240d24de9dSSimon Glass lookup_name = lookup_name.lower() 3250d24de9dSSimon Glass 3260d24de9dSSimon Glass if level > 10: 3270d24de9dSSimon Glass raise OSError, "Recursive email alias at '%s'" % lookup_name 3280d24de9dSSimon Glass 3290d24de9dSSimon Glass out_list = [] 3300d24de9dSSimon Glass if lookup_name: 3310d24de9dSSimon Glass if not lookup_name in alias: 3320d24de9dSSimon Glass raise ValueError, "Alias '%s' not found" % lookup_name 3330d24de9dSSimon Glass for item in alias[lookup_name]: 3340d24de9dSSimon Glass todo = LookupEmail(item, alias, level + 1) 3350d24de9dSSimon Glass for new_item in todo: 3360d24de9dSSimon Glass if not new_item in out_list: 3370d24de9dSSimon Glass out_list.append(new_item) 3380d24de9dSSimon Glass 3390d24de9dSSimon Glass #print "No match for alias '%s'" % lookup_name 3400d24de9dSSimon Glass return out_list 3410d24de9dSSimon Glass 3420d24de9dSSimon Glassdef GetTopLevel(): 3430d24de9dSSimon Glass """Return name of top-level directory for this git repo. 3440d24de9dSSimon Glass 3450d24de9dSSimon Glass Returns: 3460d24de9dSSimon Glass Full path to git top-level directory 3470d24de9dSSimon Glass 3480d24de9dSSimon Glass This test makes sure that we are running tests in the right subdir 3490d24de9dSSimon Glass 350a970048eSDoug Anderson >>> os.path.realpath(os.path.dirname(__file__)) == \ 351a970048eSDoug Anderson os.path.join(GetTopLevel(), 'tools', 'patman') 3520d24de9dSSimon Glass True 3530d24de9dSSimon Glass """ 3540d24de9dSSimon Glass return command.OutputOneLine('git', 'rev-parse', '--show-toplevel') 3550d24de9dSSimon Glass 3560d24de9dSSimon Glassdef GetAliasFile(): 3570d24de9dSSimon Glass """Gets the name of the git alias file. 3580d24de9dSSimon Glass 3590d24de9dSSimon Glass Returns: 3600d24de9dSSimon Glass Filename of git alias file, or None if none 3610d24de9dSSimon Glass """ 3620d24de9dSSimon Glass fname = command.OutputOneLine('git', 'config', 'sendemail.aliasesfile') 3630d24de9dSSimon Glass if fname: 3640d24de9dSSimon Glass fname = os.path.join(GetTopLevel(), fname.strip()) 3650d24de9dSSimon Glass return fname 3660d24de9dSSimon Glass 36787d65558SVikram Narayanandef GetDefaultUserName(): 36887d65558SVikram Narayanan """Gets the user.name from .gitconfig file. 36987d65558SVikram Narayanan 37087d65558SVikram Narayanan Returns: 37187d65558SVikram Narayanan User name found in .gitconfig file, or None if none 37287d65558SVikram Narayanan """ 37387d65558SVikram Narayanan uname = command.OutputOneLine('git', 'config', '--global', 'user.name') 37487d65558SVikram Narayanan return uname 37587d65558SVikram Narayanan 37687d65558SVikram Narayanandef GetDefaultUserEmail(): 37787d65558SVikram Narayanan """Gets the user.email from the global .gitconfig file. 37887d65558SVikram Narayanan 37987d65558SVikram Narayanan Returns: 38087d65558SVikram Narayanan User's email found in .gitconfig file, or None if none 38187d65558SVikram Narayanan """ 38287d65558SVikram Narayanan uemail = command.OutputOneLine('git', 'config', '--global', 'user.email') 38387d65558SVikram Narayanan return uemail 38487d65558SVikram Narayanan 3850d24de9dSSimon Glassdef Setup(): 3860d24de9dSSimon Glass """Set up git utils, by reading the alias files.""" 3870d24de9dSSimon Glass # Check for a git alias file also 3880d24de9dSSimon Glass alias_fname = GetAliasFile() 3890d24de9dSSimon Glass if alias_fname: 3900d24de9dSSimon Glass settings.ReadGitAliases(alias_fname) 3910d24de9dSSimon Glass 3920d24de9dSSimon Glassif __name__ == "__main__": 3930d24de9dSSimon Glass import doctest 3940d24de9dSSimon Glass 3950d24de9dSSimon Glass doctest.testmod() 396