script/helpers.py: remove stray newline from git parameter
[mplayer-build.git] / script / helpers.py
blob10dc88f5967b563761d60a6b5ccdc86963c7cc52
1 import os
2 from os import path
3 import types
4 from subprocess import Popen, PIPE, check_call
6 # Arch Linux thought it was a good idea to suddenly switch the "python"
7 # binary to point to python3...
8 version3error = """
9 This script is written for Python version 2, but for some reason
10 it's being run under incompatible version 3. If you didn't do anything
11 yourself to explicitly change the version then the reason is probably
12 that your system links plain "python" to "python3" instead of a
13 backwards-compatible version. Arch Linux reportedly did this.
14 You may be able to make things work by changing the first line of all
15 Python scripts from "#!/usr/bin/env python" to "#!/usr/bin/env python2".
16 Blame your distro for the inconvenience.
17 """
18 import sys
19 if sys.version_info > (3,):
20 raise Exception(version3error)
22 def run_command(args):
23 # interpret a string as a whitespace-separated list of executable+arguments
24 if isinstance(args, types.StringTypes):
25 args = args.split()
26 t = Popen(args, stdout=PIPE)
27 stdout = t.communicate()[0]
28 if t.returncode != 0:
29 raise OSError("Call %s failed" % str(args))
30 return stdout
32 class GitWrapper(object):
33 def __init__(self):
34 self.shallow = False
35 self.supports_nofetch = True
36 v = run_command('git --version')
37 prefix = 'git version '
38 def error():
39 sys.stderr.write('Cannot parse "git --version" output, '
40 'assuming new version')
41 if not v.startswith(prefix):
42 error()
43 return
44 v = v[len(prefix):]
45 try:
46 v = [int(n) for n in v.split('.')[:3]]
47 except:
48 error()
49 return
50 if v < [1, 6, 2]:
51 self.supports_nofetch = False
53 def submodule_clone(self, name):
54 if self.shallow:
55 # Use a depth greater than 1 for shallow clones to reduce the
56 # chance that required submodule versions are not fetched when
57 # all branch heads in the corresponding repo have moved ahead.
58 shallow_args = ['--depth', '100']
59 else:
60 shallow_args = []
61 if self.supports_nofetch:
62 nofetch_args = ['--no-fetch']
63 else:
64 nofetch_args = []
65 if path.exists(path.join(name, '.git')):
66 # If the submodule already exists just try to update it
67 check_call('git submodule sync'.split()+[name])
68 check_call('git submodule update'.split()+[name])
69 else:
70 # Do things manually instead of using "git submodule update --init",
71 # because git's sucky submodule support has no way of giving
72 # options to the "git clone" command that would be needed for
73 # shallow clones.
74 repo_addr = run_command('git config --get submodule.%s.url'
75 % name).strip()
76 # old git versions fail to clone over an empty directory
77 try:
78 os.rmdir(name)
79 except:
80 # Don't fail if it already doesn't exist - having other
81 # failure cases continue and fail later is OK.
82 pass
83 check_call('git clone'.split() + shallow_args + [repo_addr, name])
84 check_call('git submodule update'.split() + nofetch_args + [name])
86 def get_config(self):
87 output = run_command('git config --null --list')
88 result = {}
89 for line in output.split(chr(0)):
90 if not line:
91 continue
92 name, value = line.split('\n', 1)
93 result[name] = value
94 return result
96 def get_submodules(self):
97 output = run_command('git ls-files --stage')
98 result = []
99 for line in output.splitlines():
100 mode, sha, stage, path = line.split(None, 3)
101 if mode != '160000':
102 continue
103 result.append(path)
104 return result
106 def foreach_submodule(self, func, recurse=True):
107 for module in self.get_submodules():
108 if path.exists(path.join(module, '.git')):
109 os.chdir(module)
110 func()
111 if recurse:
112 self.foreach_submodule(func)
113 os.chdir('..')
115 def foreach_module(self, func):
116 func()
117 self.foreach_submodule(func)
120 def parse_configfile(filename):
121 if not path.exists(filename):
122 return []
123 args = []
124 f = open(filename)
125 for line in f:
126 line = line.strip()
127 if not line or line.startswith('#'):
128 continue
129 args.append(line)
130 f.close()
131 return args