]> git.donarmstrong.com Git - neurodebian.git/blob - tools/blends-inject
minor additions to blends-inject
[neurodebian.git] / tools / blends-inject
1 #!/usr/bin/python
2 #emacs: -*- mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- 
3 #ex: set sts=4 ts=4 sw=4 noet:
4
5 __author__ = 'Yaroslav Halchenko'
6 __version__ = 'XXX'
7 __copyright__ = 'Copyright (c) 2010 Yaroslav Halchenko'
8 __license__ = 'GPL'
9
10 import re
11 import os.path
12 from copy import deepcopy
13 from debian_bundle import deb822
14 from debian.changelog import Changelog
15
16 topdir = '/home/yoh/deb/gits/pkg-exppsy/brian'
17
18 blends_file = os.path.join(topdir, 'debian/blends')
19
20
21 def parse_debian_blends(f='debian/blends'):
22     """Parses debian/blends file
23
24     Returns unprocessed list of customized Deb822 entries
25     """
26     # Linearize all the paragraphs since we are not using them
27     items = []
28     for p in deb822.Deb822.iter_paragraphs(open(f)):
29         items += p.items()
30
31     # Traverse and collect things
32     format_ = 'udd'
33     format_clean = False # do not propagate fields into a new pkg if True
34     pkg = None
35     pkgs = []
36     tasks = []
37
38     for k, v in items:
39         k = k.lower()
40         if k == 'format':
41             format_ = v.strip()
42             format_clean = format_.endswith('-clean')
43             if format_clean:
44                 format_ = format_[:-6]
45         elif k == 'tasks':
46             tasks = v.split(',')
47             newtasks = True                 # either we need to provide tune-ups
48                                             # for current package
49         elif k == 'depends':                # new package
50             if format_clean or pkg is None:
51                 pkg = deb822.Deb822()
52             else:
53                 pkg = deepcopy(pkg)
54             pkg['Depends'] = v
55             pkgs.append(pkg)
56             pkg.tasks = dict( (t, deb822.OrderedSet()) for t in tasks )
57             pkg.format = format_
58             newtasks = False
59         else:
60             if newtasks:
61                 # Add customization
62                 for t in tasks:
63                     if not t in pkg.tasks:
64                         pkg.tasks[t] = deb822.Deb822Dict()
65                     pkg.tasks[t][k] = v
66             else:
67                 # just store the key in the pkg itself
68                 pkg[k] = v
69     return pkgs
70
71 def expand_pkgs(pkgs):
72     """In-place modification of pkgs taking if necessary additional
73     information from Debian materials, and pruning empty fields
74     """
75     debianm = None
76     # Expand packages which format is complete
77     for pkg in pkgs:
78         if pkg.format == 'complete':
79             # expanding, for that we need debian/control
80             if debianm is None:
81                 debianm = DebianMaterials(topdir)
82             for k, m in (('License', lambda: debianm.get_license(pkg['Depends'])),
83                          ('WNPP', debianm.get_wnpp),
84                          ('Pkg-description',
85                           lambda: debianm.binaries[pkg['Depends']]['Description']),
86                          ('Responsible', debianm.get_responsible),
87                          ('Homepage', lambda: debianm.source.get('Homepage', None))):
88                 if pkg.get(k, None):
89                     continue
90                 v = m()
91                 if v:
92                     pkg[k] = v
93             # VCS fields
94             pkg.update(debianm.get_vcsfields())
95
96         # Perform string completions and removals
97         for k,v in pkg.iteritems():
98             pkg[k] = v % pkg
99             if v is None or not len(v.strip()):
100                 pkg.pop(k)
101
102 class DebianMaterials(object):
103     """Extract selected information from an existing debian/
104     """
105     _WNPP_RE = re.compile('^ *\* *Initial release.*closes:? #(?P<bug>[0-9]*).*', re.I)
106
107     def __init__(self, topdir):
108         #self.topdir = topdir
109         self._debiandir = os.path.join(topdir, 'debian')
110         self._source = None
111         self._binaries = None
112
113     @property
114     def source(self):
115         if self._source is None:
116             self._assign_packages()
117         return self._source
118
119     @property
120     def binaries(self):
121         if self._binaries is None:
122             self._assign_packages()
123         return self._binaries
124
125     def fpath(self, name):
126         return os.path.join(self._debiandir, name)
127
128     def _assign_packages(self):
129         try:
130             control = deb822.Deb822.iter_paragraphs(
131                 open(self.fpath('control')))
132         except Exception, e:
133             raise RuntimeError(
134                   "Cannot parse %s file necessary for the %s package entry. Error: %s"
135                   % (control_file, pkg['Depends'], str(e)))
136         self._binaries = {}
137         self._source = None
138         for v in control:
139             if v.get('Source', None):
140                 self._source = v
141             else:
142                 self._binaries[v['Package']] = v
143
144     def get_license(self, package=None, first_only=True):
145         """Return a license(s). Parsed out from debian/copyright if it is
146         in machine readable format
147         """
148         licenses = []
149         # may be package should carry custom copyright file
150         copyright_file_ = self.fpath('%s.copyright' % package)
151         if package and os.path.exists(copyright_file_):
152             copyright_file = copyright_file_
153         else:
154             copyright_file = self.fpath('copyright')
155
156         try:
157             for p in deb822.Deb822.iter_paragraphs(open(copyright_file)):
158                 if not 'Files' in p or p['Files'].strip().startswith('debian/'):
159                     continue
160                 l = p['License']
161                 # Take only the short version of first line
162                 l = re.sub('\n.*', '', l).strip()
163                 if not len(l):
164                     l = 'custom'
165                 if not l in licenses:
166                     licenses.append(l)
167                     if first_only:
168                         break
169         except Exception, e:
170             # print e
171             return None
172         return ', '.join(licenses)
173
174     def get_wnpp(self):
175         """Search for a template changelog entry closing "Initial bug
176         """
177         for l in open(self.fpath('changelog')):
178             rr = self._WNPP_RE.match(l)
179             if rr:
180                 return rr.groupdict()['bug']
181         return None
182
183     def get_responsible(self):
184         """Returns responsible, atm -- maintainer
185         """
186         return self.source['Maintainer']
187
188     def get_vcsfields(self):
189         vcs = deb822.Deb822()
190         for f,v in self._source.iteritems():
191             if f.lower().startswith('vcs-'):
192                 vcs[f] = v
193         return vcs
194
195 pkgs = parse_debian_blends(blends_file)
196 expand_pkgs(pkgs)
197
198 print '\n'.join(str(p) for p in pkgs)
199 #print pkgs[0]