source: rtems-source-builder/source-builder/sb/git.py @ b0f9e30

4.104.114.95
Last change on this file since b0f9e30 was b0f9e30, checked in by Chris Johns <chrisj@…>, on 03/17/15 at 21:21:34

Add merge to the git and download modules to merge after a fetch.

Update the RTEMS tools and newlib-git to merge after the fetch.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2013 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
24import os
25
26import error
27import execute
28import log
29import options
30import path
31
32class repo:
33    """An object to manage a git repo."""
34
35    def _git_exit_code(self, ec):
36        if ec:
37            raise error.general('git command failed (%s): %d' % (self.git, ec))
38
39    def _run(self, args, check = False):
40        e = execute.capture_execution()
41        if path.exists(self.path):
42            cwd = self.path
43        else:
44            cwd = None
45        cmd = [self.git] + args
46        log.trace('cmd: (%s) %s' % (str(cwd), ' '.join(cmd)))
47        exit_code, proc, output = e.spawn(cmd, cwd = path.host(cwd))
48        log.trace(output)
49        if check:
50            self._git_exit_code(exit_code)
51        return exit_code, output
52
53    def __init__(self, _path, opts = None, macros = None):
54        self.path = _path
55        self.opts = opts
56        if macros is None and opts is not None:
57            self.macros = opts.defaults
58        else:
59            self.macros = macros
60        if self.macros is None:
61            self.git = 'git'
62        else:
63            self.git = self.macros.expand('%{__git}')
64
65    def git_version(self):
66        ec, output = self._run(['--version'], True)
67        gvs = output.split()
68        if len(gvs) < 3:
69            raise error.general('invalid version string from git: %s' % (output))
70        vs = gvs[2].split('.')
71        if len(vs) != 4:
72            raise error.general('invalid version number from git: %s' % (gvs[2]))
73        return (int(vs[0]), int(vs[1]), int(vs[2]), int(vs[3]))
74
75    def clone(self, url, _path):
76        ec, output = self._run(['clone', url, path.host(_path)], check = True)
77
78    def fetch(self):
79        ec, output = self._run(['fetch'], check = True)
80
81    def merge(self):
82        ec, output = self._run(['merge'], check = True)
83
84    def pull(self):
85        ec, output = self._run(['pull'], check = True)
86
87    def reset(self, args):
88        if type(args) == str:
89            args = [args]
90        ec, output = self._run(['reset'] + args, check = True)
91
92    def branch(self):
93        ec, output = self._run(['branch'])
94        if ec == 0:
95            for b in output.split('\n'):
96                if b[0] == '*':
97                    return b[2:]
98        return None
99
100    def checkout(self, branch = 'master'):
101        ec, output = self._run(['checkout', branch], check = True)
102
103    def submodule(self, module):
104        ec, output = self._run(['submodule', 'update', '--init', module], check = True)
105
106    def clean(self, args = []):
107        if type(args) == str:
108            args = [args]
109        ec, output = self._run(['clean'] + args, check = True)
110
111    def status(self):
112        _status = {}
113        if path.exists(self.path):
114            ec, output = self._run(['status'])
115            if ec == 0:
116                state = 'none'
117                for l in output.split('\n'):
118                    if l.startswith('# '):
119                        l = l[2:]
120                    if l.startswith('On branch '):
121                        _status['branch'] = l[len('On branch '):]
122                    elif l.startswith('Changes to be committed:'):
123                        state = 'staged'
124                    elif l.startswith('Changes not staged for commit:'):
125                        state = 'unstaged'
126                    elif l.startswith('Untracked files:'):
127                        state = 'untracked'
128                    elif l.startswith('HEAD detached'):
129                        state = 'detached'
130                    elif state != 'none' and len(l.strip()) != 0:
131                        if l[0].isspace():
132                            l = l.strip()
133                            if l[0] != '(':
134                                if state not in _status:
135                                    _status[state] = []
136                                l = l[1:]
137                                if ':' in l:
138                                    l = l.split(':')[1]
139                                _status[state] += [l.strip()]
140        return _status
141
142    def dirty(self):
143        _status = self.status()
144        return not (len(_status) == 1 and 'branch' in _status)
145
146    def valid(self):
147        if path.exists(self.path):
148            ec, output = self._run(['status'])
149            return ec == 0
150        return False
151
152    def remotes(self):
153        _remotes = {}
154        ec, output = self._run(['config', '--list'])
155        if ec == 0:
156            for l in output.split('\n'):
157                if l.startswith('remote'):
158                    ls = l.split('=')
159                    if len(ls) >= 2:
160                        rs = ls[0].split('.')
161                        if len(rs) == 3:
162                            r_name = rs[1]
163                            r_type = rs[2]
164                            if r_name not in _remotes:
165                                _remotes[r_name] = {}
166                            if r_type not in _remotes[r_name]:
167                                _remotes[r_name][r_type] = []
168                            _remotes[r_name][r_type] = '='.join(ls[1:])
169        return _remotes
170
171    def email(self):
172        _email = None
173        _name = None
174        ec, output = self._run(['config', '--list'])
175        if ec == 0:
176            for l in output.split('\n'):
177                if l.startswith('user.email'):
178                    ls = l.split('=')
179                    if len(ls) >= 2:
180                        _email = ls[1]
181                elif l.startswith('user.name'):
182                    ls = l.split('=')
183                    if len(ls) >= 2:
184                        _name = ls[1]
185        if _email is not None:
186            if _name is not None:
187                _email = '%s <%s>' % (_name, _email)
188            return _email
189        return None
190
191    def head(self):
192        hash = ''
193        ec, output = self._run(['log', '-n', '1'])
194        if ec == 0:
195            l1 = output.split('\n')[0]
196            if l1.startswith('commit '):
197                hash = l1[len('commit '):]
198        return hash
199
200if __name__ == '__main__':
201    import sys
202    opts = options.load(sys.argv)
203    g = repo('.', opts)
204    print g.git_version()
205    print g.valid()
206    print g.status()
207    print g.clean()
208    print g.remotes()
209    print g.email()
210    print g.head()
Note: See TracBrowser for help on using the repository browser.