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,
29 from optparse
import OptionParser
32 if 'XDG_DATA_HOME' not in os
.environ
:
33 os
.environ
['XDG_DATA_HOME'] = os
.path
.join(os
.environ
['HOME'], \
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'
46 with
open(_dpath
+'.SECURE', 'w') as trusted_file
:
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
):
77 Reads the lines from the given file and checks if these lines are valid.
79 configs
= {'separator' : separator
}
81 filename
= _abs(filename
)
83 cfile
= open(filename
, 'r')
85 for line
in cfile
.readlines():
88 if line
.startswith('#') or line
== '':
94 key
, value
= line
.split('=')
101 key
, value
= line
.split('=')
104 optparser
.error('{file} contains an invalid line'\
105 .format(file=filename
))
108 value
= value
.strip()
110 if key
== 'files' or key
== 'ignore':
112 if configs
['separator'] in value
:
113 value
= value
.split(configs
['separator'])
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
]
135 optparser
.error('{file} does not exist'.format(file=file))
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.
151 if not file.endswith(os
.sep
):
154 subfiles
= [file+subfile
for subfile
in os
.listdir(file)]
155 files
.extend(subdir(subfiles
))
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
)
174 if file.startswith(ign
):
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
)
199 archive_file
.add(file)
201 archive_file
.add(_trust
, os
.path
.basename(_trust
))
206 def main(options
, args
):
207 configs
= {'replace' : 0, 'files' : [], 'ignore' : [], 'separator' : ','}
209 if options
.separator
:
210 configs
['separator'] = options
.separator
213 configs
.update(get_config(options
.config
, configs
['separator']))
216 configs
['archive'] = options
.archive
219 if configs
['separator'] not in options
.ignore
:
220 ignore
= [options
.ignore
]
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
)
239 print('--> '+_abs(name
))
241 if configs
['replace']:
242 conf_filename
= os
.path
.basename(options
.config
)
243 rpfilename
= _dpath
+ conf_filename
246 rpfile
= file(rpfilename
, 'r')
247 rep_files
= [files
.strip() for files
in rpfile
.readlines()]
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
))
265 rpfile
= file(rpfilename
, 'w')
269 elif options
.restore
:
270 archive_name
= _abs(options
.restore
)
273 print('<-- '+archive_name
)
275 if _ex(archive_name
):
276 archive_file
= tarfile
.open(archive_name
, 'r')
278 archive_file
.getmember(os
.path
.basename(_trust
))
282 members
= archive_file
.getmembers()
284 for member
in members
:
285 if member
.name
!= '.SECURE':
287 archive_file
.extract(member
, '/')
290 archive_file
.extractall('/')
293 members
= archive_file
.getmembers()
295 for member
in members
:
297 if member
.name
!= '.SECURE':
300 if replace
.startswith('/'):
301 replace
= replace
[1:]
303 if member
.name
.startswith(replace
):
308 archive_file
.extract(member
, '/')
311 optparser
.error("{file} is not a trusted archive"\
312 .format(file=archive_name
))
315 optparser
.error("{file} does not exist".format(file=archive_name
))
317 optparser
.print_help()
319 if __name__
== "__main__":
320 options
, args
= optparser
.parse_args()
323 except KeyboardInterrupt:
324 optparser
.error('KeyboardInterrupt')