updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / apbp / apbp.py
blob7777d6c337389a071f720c5b6970dfaf0ab43ec2
1 #!/usr/bin/python
3 # apbp.py
5 # Copyright 2010 Alexander Preisinger <alexander.preisinger@gmail.com>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 # MA 02110-1301, USA.
22 __version__ = "1.0"
24 import os
25 import os.path
26 import sys
27 import tarfile
28 import datetime
29 from optparse import OptionParser
31 # Cron fix
32 if 'XDG_DATA_HOME' not in os.environ:
33 os.environ['XDG_DATA_HOME'] = os.path.join(os.environ['HOME'], \
34 '.local/share')
35 # Cron fix
37 _ex = os.path.exists
38 _abs = os.path.abspath
39 _isdir = os.path.isdir
40 _dpath = _abs(os.path.join(os.environ['XDG_DATA_HOME'], 'apbp')) + os.sep
41 _trust = _dpath+'.SECURE'
43 if not _ex(_dpath):
44 os.makedirs(_dpath)
46 with open(_dpath+'.SECURE', 'w') as trusted_file:
47 pass
50 optparser = OptionParser("""\n{name} [OPTIONS] [ADDITIONAL-FILES]
51 {name} -x ARCHIVE FILES
52 {name} -c CONFIG-FILE [ADDITIONAL-FILES]""".format(name=sys.argv[0]))
54 optparser.add_option("-c", "--config", dest="config", \
55 help="use a config", metavar="FILENAME")
57 optparser.add_option("-x", "--archive", dest="archive", \
58 help="choose an archive (gzip, bzip2)", metavar="TAR-ARCHIVE")
60 optparser.add_option("-i", "--ignore", dest="ignore", \
61 help="""ignores files in the given path
62 use comma to sepperate paths (e.g. FILE1,PATH1,FILE2,...)""", metavar="FILE")
64 optparser.add_option("-r", "--restore", dest="restore", \
65 help="restores the saved data, will overwrite the original files", \
66 metavar="TAR-ARCHIVE")
68 optparser.add_option("-s", "--separator", dest="separator", \
69 help="use a different separator for lists of files", metavar="CHAR")
71 optparser.add_option("-v", "--verbose", action="store_true", dest="verbose",
72 default=False, help="verbose output")
75 def get_config(filename, separator):
76 """
77 Reads the lines from the given file and checks if these lines are valid.
78 """
79 configs = {'separator' : separator}
81 filename = _abs(filename)
82 if _ex(filename):
83 cfile = open(filename, 'r')
85 for line in cfile.readlines():
86 line = line.strip()
88 if line.startswith('#') or line == '':
89 continue
90 else:
92 if line == 'replace':
93 try:
94 key, value = line.split('=')
95 except ValueError:
96 key = line
97 value = 1
99 else:
100 try:
101 key, value = line.split('=')
103 except ValueError:
104 optparser.error('{file} contains an invalid line'\
105 .format(file=filename))
107 key = key.strip()
108 value = value.strip()
110 if key == 'files' or key == 'ignore':
112 if configs['separator'] in value:
113 value = value.split(configs['separator'])
114 else:
115 value = [value]
117 configs[key] = value
119 cfile.close()
121 return configs
123 else:
124 optparser.error('{file} does not exist'.format(file=filename))
127 def abs_and_check(files):
129 Returns the files with the absolute pathname and checks if the file exists.
131 files = [_abs(file) for file in files]
133 for file in files:
134 if not _ex(file):
135 optparser.error('{file} does not exist'.format(file=file))
137 return files
140 def subdir(files):
142 Checks if the file is a directory. If true then the directory will be
143 removed from the filelist and its files will be added and also this files
144 will be checked if they are directories and so on.
146 for file in files:
148 if _isdir(file):
149 files.remove(file)
151 if not file.endswith(os.sep):
152 file = file + os.sep
154 subfiles = [file+subfile for subfile in os.listdir(file)]
155 files.extend(subdir(subfiles))
157 return files
160 def get_files(afiles, ignore):
162 Removes the ignored files form the file list.
164 afiles = abs_and_check(afiles)
165 ignore = abs_and_check(ignore)
167 afiles = subdir(afiles)
169 nfiles = []
170 for file in afiles:
171 IGN = False
173 for ign in ignore:
174 if file.startswith(ign):
175 IGN = True
177 if not IGN:
178 nfiles.append(file)
180 return nfiles
183 def archive(archive_name, files, verbose=False):
185 Finally archives the file under the given name
187 archive_type = archive_name.split('.')[-1]
189 if archive_type != 'gz' and archive_type != 'bz2':
190 optparser.error('the archive has to be a *.tar.gz or a *.tar.bz2 file')
192 archive_file = tarfile.open(archive_name, 'w:%s' % archive_type)
194 for file in files:
196 if verbose:
197 print(file)
199 archive_file.add(file)
201 archive_file.add(_trust, os.path.basename(_trust))
203 archive_file.close()
206 def main(options, args):
207 configs = {'replace' : 0, 'files' : [], 'ignore' : [], 'separator' : ','}
209 if options.separator:
210 configs['separator'] = options.separator
212 if options.config:
213 configs.update(get_config(options.config, configs['separator']))
215 if options.archive:
216 configs['archive'] = options.archive
218 if options.ignore:
219 if configs['separator'] not in options.ignore:
220 ignore = [options.ignore]
222 else:
223 ignore = options.ignore.split(configs['separator'])
225 configs['ignore'].extend(ignore)
227 configs['files'].extend(args)
229 if 'archive' in configs:
230 files = get_files(configs['files'], configs['ignore'])
232 ctime = datetime.datetime.now()
233 # Support for time formatting in the archive name
234 name = ctime.strftime(configs['archive'])
236 archive(name, files, options.verbose)
238 if options.verbose:
239 print('--> '+_abs(name))
241 if configs['replace']:
242 conf_filename = os.path.basename(options.config)
243 rpfilename = _dpath + conf_filename
245 if _ex(rpfilename):
246 rpfile = file(rpfilename, 'r')
247 rep_files = [files.strip() for files in rpfile.readlines()]
248 rpfile.close()
250 rep_no = int(configs['replace'])
251 if rep_no == len(rep_files):
253 del_filename = rep_files.pop(rep_no-1)
255 if _ex(del_filename):
256 if name != del_filename:
257 os.remove(del_filename)
259 rep_files.insert(0, name)
260 rpfile = file(rpfilename, 'w')
261 rpfile.write('\n'.join(rep_files))
262 rpfile.close()
264 else:
265 rpfile = file(rpfilename, 'w')
266 rpfile.write(name)
267 rpfile.close
269 elif options.restore:
270 archive_name = _abs(options.restore)
272 if options.verbose:
273 print('<-- '+archive_name)
275 if _ex(archive_name):
276 archive_file = tarfile.open(archive_name, 'r')
277 try:
278 archive_file.getmember(os.path.basename(_trust))
280 if len(args) == 0:
281 if options.verbose:
282 members = archive_file.getmembers()
284 for member in members:
285 if member.name != '.SECURE':
286 print(member.name)
287 archive_file.extract(member, '/')
289 else:
290 archive_file.extractall('/')
292 else:
293 members = archive_file.getmembers()
295 for member in members:
297 if member.name != '.SECURE':
298 for replace in args:
300 if replace.startswith('/'):
301 replace = replace[1:]
303 if member.name.startswith(replace):
305 if options.verbose:
306 print(member.name)
308 archive_file.extract(member, '/')
310 except:
311 optparser.error("{file} is not a trusted archive"\
312 .format(file=archive_name))
314 else:
315 optparser.error("{file} does not exist".format(file=archive_name))
316 else:
317 optparser.print_help()
319 if __name__ == "__main__":
320 options, args = optparser.parse_args()
321 try:
322 main(options, args)
323 except KeyboardInterrupt:
324 optparser.error('KeyboardInterrupt')