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

4.104.9
Last change on this file since 3a972f6 was 3a972f6, checked in by Chris Johns <chrisj@…>, on Mar 7, 2016 at 12:56:02 AM

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
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
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
24from __future__ import print_function
25
26import os
27
28import error
29import execute
30import log
31import options
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()
43        if path.exists(self.path):
44            cwd = self.path
45        else:
46            cwd = None
47        cmd = [self.git] + args
48        log.trace('cmd: (%s) %s' % (str(cwd), ' '.join(cmd)))
49        exit_code, proc, output = e.spawn(cmd, cwd = path.host(cwd))
50        log.trace(output)
51        if check:
52            self._git_exit_code(exit_code)
53        return exit_code, output
54
55    def __init__(self, _path, opts = None, macros = None):
56        self.path = _path
57        self.opts = opts
58        if macros is None and opts is not None:
59            self.macros = opts.defaults
60        else:
61            self.macros = macros
62        if self.macros is None:
63            self.git = 'git'
64        else:
65            self.git = self.macros.expand('%{__git}')
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
77    def clone(self, url, _path):
78        ec, output = self._run(['clone', url, path.host(_path)], check = True)
79
80    def fetch(self):
81        ec, output = self._run(['fetch'], check = True)
82
83    def merge(self):
84        ec, output = self._run(['merge'], check = True)
85
86    def pull(self):
87        ec, output = self._run(['pull'], check = True)
88
89    def reset(self, args):
90        if type(args) == str:
91            args = [args]
92        ec, output = self._run(['reset'] + args, check = True)
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'):
103        ec, output = self._run(['checkout', branch], check = True)
104
105    def submodule(self, module):
106        ec, output = self._run(['submodule', 'update', '--init', module], check = True)
107
108    def clean(self, args = []):
109        if type(args) == str:
110            args = [args]
111        ec, output = self._run(['clean'] + args, check = True)
112
113    def status(self):
114        _status = {}
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'):
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:'):
125                        state = 'staged'
126                    elif l.startswith('Changes not staged for commit:'):
127                        state = 'unstaged'
128                    elif l.startswith('Untracked files:'):
129                        state = 'untracked'
130                    elif l.startswith('HEAD detached'):
131                        state = 'detached'
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()]
142        return _status
143
144    def dirty(self):
145        _status = self.status()
146        return not (len(_status) == 1 and 'branch' in _status)
147
148    def valid(self):
149        if path.exists(self.path):
150            ec, output = self._run(['status'])
151            return ec == 0
152        return False
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
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
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
204    opts = options.load(sys.argv)
205    g = repo('.', opts)
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.