source: rtems-source-builder/source-builder/sb/git.py @ 3a972f6

4.104.95
Last change on this file since 3a972f6 was 3a972f6, checked in by Chris Johns <chrisj@…>, on 03/07/16 at 00:56:02

sb: Update code base to support Python3 and Python2.

Fix Windows support to allow MSYS2 Python to be used.

Updates #2619.

  • Property mode set to 100644
File size: 7.0 KB
RevLine 
[d7e4900]1#
2# RTEMS Tools Project (http://www.rtems.org/)
[3a972f6]3# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
[d7e4900]4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Permission to use, copy, modify, and/or distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#
21# Provide some basic access to the git command.
22#
23
[3a972f6]24from __future__ import print_function
25
[d7e4900]26import os
27
28import error
29import execute
[5142bec]30import log
[cb12e48]31import options
[d7e4900]32import path
33
34class repo:
35    """An object to manage a git repo."""
36
37    def _git_exit_code(self, ec):
38        if ec:
39            raise error.general('git command failed (%s): %d' % (self.git, ec))
40
41    def _run(self, args, check = False):
42        e = execute.capture_execution()
[649a64c]43        if path.exists(self.path):
44            cwd = self.path
45        else:
46            cwd = None
[5142bec]47        cmd = [self.git] + args
48        log.trace('cmd: (%s) %s' % (str(cwd), ' '.join(cmd)))
[5237f1cc]49        exit_code, proc, output = e.spawn(cmd, cwd = path.host(cwd))
[5142bec]50        log.trace(output)
[d7e4900]51        if check:
52            self._git_exit_code(exit_code)
53        return exit_code, output
54
[74da24c]55    def __init__(self, _path, opts = None, macros = None):
[d7e4900]56        self.path = _path
[cb12e48]57        self.opts = opts
[74da24c]58        if macros is None and opts is not None:
[cb12e48]59            self.macros = opts.defaults
60        else:
61            self.macros = macros
[d790668]62        if self.macros is None:
63            self.git = 'git'
64        else:
65            self.git = self.macros.expand('%{__git}')
[d7e4900]66
67    def git_version(self):
68        ec, output = self._run(['--version'], True)
69        gvs = output.split()
70        if len(gvs) < 3:
71            raise error.general('invalid version string from git: %s' % (output))
72        vs = gvs[2].split('.')
73        if len(vs) != 4:
74            raise error.general('invalid version number from git: %s' % (gvs[2]))
75        return (int(vs[0]), int(vs[1]), int(vs[2]), int(vs[3]))
76
[5237f1cc]77    def clone(self, url, _path):
78        ec, output = self._run(['clone', url, path.host(_path)], check = True)
[649a64c]79
[b0c2756]80    def fetch(self):
81        ec, output = self._run(['fetch'], check = True)
[649a64c]82
[b0f9e30]83    def merge(self):
84        ec, output = self._run(['merge'], check = True)
85
[649a64c]86    def pull(self):
[b0c2756]87        ec, output = self._run(['pull'], check = True)
[649a64c]88
89    def reset(self, args):
90        if type(args) == str:
91            args = [args]
[b0c2756]92        ec, output = self._run(['reset'] + args, check = True)
[649a64c]93
94    def branch(self):
95        ec, output = self._run(['branch'])
96        if ec == 0:
97            for b in output.split('\n'):
98                if b[0] == '*':
99                    return b[2:]
100        return None
101
102    def checkout(self, branch = 'master'):
[b0c2756]103        ec, output = self._run(['checkout', branch], check = True)
[649a64c]104
[5601b9c]105    def submodule(self, module):
106        ec, output = self._run(['submodule', 'update', '--init', module], check = True)
107
[c21f09e]108    def clean(self, args = []):
[8c19df2]109        if type(args) == str:
110            args = [args]
111        ec, output = self._run(['clean'] + args, check = True)
112
[d7e4900]113    def status(self):
114        _status = {}
[649a64c]115        if path.exists(self.path):
116            ec, output = self._run(['status'])
117            if ec == 0:
118                state = 'none'
119                for l in output.split('\n'):
[c21f09e]120                    if l.startswith('# '):
121                        l = l[2:]
122                    if l.startswith('On branch '):
123                        _status['branch'] = l[len('On branch '):]
124                    elif l.startswith('Changes to be committed:'):
[649a64c]125                        state = 'staged'
[c21f09e]126                    elif l.startswith('Changes not staged for commit:'):
[649a64c]127                        state = 'unstaged'
[c21f09e]128                    elif l.startswith('Untracked files:'):
[649a64c]129                        state = 'untracked'
[c21f09e]130                    elif l.startswith('HEAD detached'):
[5601b9c]131                        state = 'detached'
[c21f09e]132                    elif state != 'none' and len(l.strip()) != 0:
133                        if l[0].isspace():
134                            l = l.strip()
135                            if l[0] != '(':
136                                if state not in _status:
137                                    _status[state] = []
138                                l = l[1:]
139                                if ':' in l:
140                                    l = l.split(':')[1]
141                                _status[state] += [l.strip()]
[d7e4900]142        return _status
143
[8c19df2]144    def dirty(self):
[d7e4900]145        _status = self.status()
[c21f09e]146        return not (len(_status) == 1 and 'branch' in _status)
[d7e4900]147
148    def valid(self):
[649a64c]149        if path.exists(self.path):
150            ec, output = self._run(['status'])
151            return ec == 0
152        return False
[d7e4900]153
154    def remotes(self):
155        _remotes = {}
156        ec, output = self._run(['config', '--list'])
157        if ec == 0:
158            for l in output.split('\n'):
159                if l.startswith('remote'):
160                    ls = l.split('=')
161                    if len(ls) >= 2:
162                        rs = ls[0].split('.')
163                        if len(rs) == 3:
164                            r_name = rs[1]
165                            r_type = rs[2]
166                            if r_name not in _remotes:
167                                _remotes[r_name] = {}
168                            if r_type not in _remotes[r_name]:
169                                _remotes[r_name][r_type] = []
170                            _remotes[r_name][r_type] = '='.join(ls[1:])
171        return _remotes
172
[97a685f]173    def email(self):
174        _email = None
175        _name = None
176        ec, output = self._run(['config', '--list'])
177        if ec == 0:
178            for l in output.split('\n'):
179                if l.startswith('user.email'):
180                    ls = l.split('=')
181                    if len(ls) >= 2:
182                        _email = ls[1]
183                elif l.startswith('user.name'):
184                    ls = l.split('=')
185                    if len(ls) >= 2:
186                        _name = ls[1]
187        if _email is not None:
188            if _name is not None:
189                _email = '%s <%s>' % (_name, _email)
190            return _email
191        return None
192
[d7e4900]193    def head(self):
194        hash = ''
195        ec, output = self._run(['log', '-n', '1'])
196        if ec == 0:
197            l1 = output.split('\n')[0]
198            if l1.startswith('commit '):
199                hash = l1[len('commit '):]
200        return hash
201
202if __name__ == '__main__':
203    import sys
[cb12e48]204    opts = options.load(sys.argv)
205    g = repo('.', opts)
[3a972f6]206    print(g.git_version())
207    print(g.valid())
208    print(g.status())
209    print(g.clean())
210    print(g.remotes())
211    print(g.email())
212    print(g.head())
Note: See TracBrowser for help on using the repository browser.