mirror of
https://git.rtems.org/rtems-tools/
synced 2025-10-19 10:05:25 +08:00
rt: Add the rtems-tester.
This commit is contained in:
201
rtemstoolkit/git.py
Normal file
201
rtemstoolkit/git.py
Normal file
@@ -0,0 +1,201 @@
|
||||
#
|
||||
# RTEMS Tools Project (http://www.rtems.org/)
|
||||
# Copyright 2010-2014 Chris Johns (chrisj@rtems.org)
|
||||
# All rights reserved.
|
||||
#
|
||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
# Provide some basic access to the git command.
|
||||
#
|
||||
|
||||
import os
|
||||
|
||||
import error
|
||||
import execute
|
||||
import log
|
||||
import options
|
||||
import path
|
||||
|
||||
class repo:
|
||||
"""An object to manage a git repo."""
|
||||
|
||||
def _git_exit_code(self, ec):
|
||||
if ec:
|
||||
raise error.general('git command failed (%s): %d' % (self.git, ec))
|
||||
|
||||
def _run(self, args, check = False):
|
||||
e = execute.capture_execution()
|
||||
if path.exists(self.path):
|
||||
cwd = self.path
|
||||
else:
|
||||
cwd = None
|
||||
cmd = [self.git] + args
|
||||
log.trace('cmd: (%s) %s' % (str(cwd), ' '.join(cmd)))
|
||||
exit_code, proc, output = e.spawn(cmd, cwd = path.host(cwd))
|
||||
log.trace(output)
|
||||
if check:
|
||||
self._git_exit_code(exit_code)
|
||||
return exit_code, output
|
||||
|
||||
def __init__(self, _path, opts, macros = None):
|
||||
self.path = _path
|
||||
self.opts = opts
|
||||
if macros is None:
|
||||
self.macros = opts.defaults
|
||||
else:
|
||||
self.macros = macros
|
||||
self.git = self.macros.expand('%{__git}')
|
||||
|
||||
def git_version(self):
|
||||
ec, output = self._run(['--version'], True)
|
||||
gvs = output.split()
|
||||
if len(gvs) < 3:
|
||||
raise error.general('invalid version string from git: %s' % (output))
|
||||
vs = gvs[2].split('.')
|
||||
if len(vs) != 4:
|
||||
raise error.general('invalid version number from git: %s' % (gvs[2]))
|
||||
return (int(vs[0]), int(vs[1]), int(vs[2]), int(vs[3]))
|
||||
|
||||
def clone(self, url, _path):
|
||||
ec, output = self._run(['clone', url, path.host(_path)], check = True)
|
||||
|
||||
def fetch(self):
|
||||
ec, output = self._run(['fetch'], check = True)
|
||||
|
||||
def pull(self):
|
||||
ec, output = self._run(['pull'], check = True)
|
||||
|
||||
def reset(self, args):
|
||||
if type(args) == str:
|
||||
args = [args]
|
||||
ec, output = self._run(['reset'] + args, check = True)
|
||||
|
||||
def branch(self):
|
||||
ec, output = self._run(['branch'])
|
||||
if ec == 0:
|
||||
for b in output.split('\n'):
|
||||
if b[0] == '*':
|
||||
return b[2:]
|
||||
return None
|
||||
|
||||
def checkout(self, branch = 'master'):
|
||||
ec, output = self._run(['checkout', branch], check = True)
|
||||
|
||||
def status(self):
|
||||
_status = {}
|
||||
if path.exists(self.path):
|
||||
ec, output = self._run(['status'])
|
||||
if ec == 0:
|
||||
state = 'none'
|
||||
for l in output.split('\n'):
|
||||
if l.startswith('# On branch '):
|
||||
_status['branch'] = l[len('# On branch '):]
|
||||
elif l.startswith('# Changes to be committed:'):
|
||||
state = 'staged'
|
||||
elif l.startswith('# Changes not staged for commit:'):
|
||||
state = 'unstaged'
|
||||
elif l.startswith('# Untracked files:'):
|
||||
state = 'untracked'
|
||||
elif state != 'none' and l[0] == '#':
|
||||
if l.strip() != '#' and not l.startswith('# ('):
|
||||
if state not in _status:
|
||||
_status[state] = []
|
||||
l = l[1:]
|
||||
if ':' in l:
|
||||
l = l.split(':')[1]
|
||||
_status[state] += [l.strip()]
|
||||
return _status
|
||||
|
||||
def clean(self):
|
||||
_status = self.status()
|
||||
return len(_status) == 1 and 'branch' in _status
|
||||
|
||||
def valid(self):
|
||||
if path.exists(self.path):
|
||||
ec, output = self._run(['status'])
|
||||
return ec == 0
|
||||
return False
|
||||
|
||||
def remotes(self):
|
||||
_remotes = {}
|
||||
ec, output = self._run(['config', '--list'])
|
||||
if ec == 0:
|
||||
for l in output.split('\n'):
|
||||
if l.startswith('remote'):
|
||||
ls = l.split('=')
|
||||
if len(ls) >= 2:
|
||||
rs = ls[0].split('.')
|
||||
if len(rs) == 3:
|
||||
r_name = rs[1]
|
||||
r_type = rs[2]
|
||||
if r_name not in _remotes:
|
||||
_remotes[r_name] = {}
|
||||
if r_type not in _remotes[r_name]:
|
||||
_remotes[r_name][r_type] = []
|
||||
_remotes[r_name][r_type] = '='.join(ls[1:])
|
||||
return _remotes
|
||||
|
||||
def email(self):
|
||||
_email = None
|
||||
_name = None
|
||||
ec, output = self._run(['config', '--list'])
|
||||
if ec == 0:
|
||||
for l in output.split('\n'):
|
||||
if l.startswith('user.email'):
|
||||
ls = l.split('=')
|
||||
if len(ls) >= 2:
|
||||
_email = ls[1]
|
||||
elif l.startswith('user.name'):
|
||||
ls = l.split('=')
|
||||
if len(ls) >= 2:
|
||||
_name = ls[1]
|
||||
if _email is not None:
|
||||
if _name is not None:
|
||||
_email = '%s <%s>' % (_name, _email)
|
||||
return _email
|
||||
return None
|
||||
|
||||
def head(self):
|
||||
hash = ''
|
||||
ec, output = self._run(['log', '-n', '1'])
|
||||
if ec == 0:
|
||||
l1 = output.split('\n')[0]
|
||||
if l1.startswith('commit '):
|
||||
hash = l1[len('commit '):]
|
||||
return hash
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
opts = options.load(sys.argv)
|
||||
g = repo('.', opts)
|
||||
print g.git_version()
|
||||
print g.valid()
|
||||
print g.status()
|
||||
print g.clean()
|
||||
print g.remotes()
|
||||
print g.email()
|
||||
print g.head()
|
Reference in New Issue
Block a user