Merge lp:~ryan-c-ahearn/backintime/command_line_interface into lp:backintime/1.0
- command_line_interface
- Merge into release-1.0
Proposed by
Ryan Ahearn
Status: | Needs review |
---|---|
Proposed branch: | lp:~ryan-c-ahearn/backintime/command_line_interface |
Merge into: | lp:backintime/1.0 |
Diff against target: |
1954 lines (+1735/-5) 30 files modified
.bzrignore (+2/-0) AUTHORS (+1/-0) README (+12/-0) cli/Makefile.template (+25/-0) cli/backintime-config (+27/-0) cli/backintime-restore (+27/-0) cli/bitconfig.py (+142/-0) cli/bitrestore.py (+131/-0) cli/configure (+12/-0) cli/copywidget.py (+67/-0) cli/debian_specific/control (+10/-0) cli/debian_specific/control.source (+14/-0) cli/debian_specific/postrm (+3/-0) cli/debian_specific/rules (+50/-0) cli/excludewidget.py (+118/-0) cli/expertwidget.py (+47/-0) cli/generalwidget.py (+93/-0) cli/includewidget.py (+118/-0) cli/optionswidget.py (+45/-0) cli/profilewidget.py (+162/-0) cli/removesnapshot.py (+51/-0) cli/removewidget.py (+114/-0) cli/restorewidget.py (+107/-0) cli/snapshotname.py (+52/-0) cli/snapshotswidget.py (+158/-0) cli/viewerwidget.py (+132/-0) common/backintime.py (+1/-1) common/logger.py (+0/-3) makedeb.sh (+1/-1) updateversion.sh (+13/-0) |
To merge this branch: | bzr merge lp:~ryan-c-ahearn/backintime/command_line_interface |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Back In Time Team | Pending | ||
Review via email: mp+20422@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 691. By Ryan Ahearn
-
Fixed bug in setting the hour to run backintime for daily/weekly/
monthly backups
Unmerged revisions
- 691. By Ryan Ahearn
-
Fixed bug in setting the hour to run backintime for daily/weekly/
monthly backups - 690. By Ryan Ahearn
-
Added gettext calls to all strings that will be displayed to the user
- 689. By Ryan Ahearn
-
Added cli entries to the updateversion script
- 688. By Ryan Ahearn
-
Added myself to the AUTHORS file
- 687. By Ryan Ahearn
-
Added sections on cli to the README
- 686. By Ryan Ahearn
-
Added simple packaging files for backintime-cli
- 685. By Ryan Ahearn
-
Uncommented the man page install lines from Makefile.template to get them installed
- 684. By Ryan Ahearn
-
Added backintime-config and backintime-restore man pages
- 683. By Ryan Ahearn
-
Can now set the backup time for daily, weekly, and monthly backups
- 682. By Ryan Ahearn
-
Added ability to name and delete snapshots from restore window
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file '.bzrignore' |
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 |
3 | +++ .bzrignore 2010-03-02 06:06:17 +0000 |
4 | @@ -0,0 +1,2 @@ |
5 | +Makefile |
6 | +common/po/*.mo |
7 | |
8 | === modified file 'AUTHORS' |
9 | --- AUTHORS 2009-11-06 13:00:42 +0000 |
10 | +++ AUTHORS 2010-03-02 06:06:17 +0000 |
11 | @@ -1,3 +1,4 @@ |
12 | Oprea Dan (<dan@le-web.org>) |
13 | Bart de Koning (<bratdaking@gmail.com>) |
14 | Richard Bailey (<rmjb@mail.com>) |
15 | +Ryan Ahearn (<ryan.c.ahearn@gmail.com>) |
16 | |
17 | === modified file 'README' |
18 | --- README 2009-11-02 13:52:00 +0000 |
19 | +++ README 2010-03-02 06:06:17 +0000 |
20 | @@ -39,6 +39,12 @@ |
21 | sudo dpkg -i backintime-common-<version>.deb |
22 | sudo dpkg -i backintime-kde4-<version>.deb |
23 | |
24 | + Command Line Interface: (python-urwid >= 0.9.9) |
25 | + |
26 | + ./makedeb.sh |
27 | + sudo dpkg -i backintime-common-<version>.deb |
28 | + sudo dpkg -i backintime-cli-<version>.deb |
29 | + |
30 | NOTE: |
31 | Ubuntu 8.04: to install KDE4 4.1 check this link: |
32 | http://news.softpedia.com/news/How-To-Install-KDE-4-1-On-Ubuntu-8-04-91034.shtml |
33 | @@ -50,6 +56,12 @@ |
34 | ./configure |
35 | make |
36 | sudo make install |
37 | + |
38 | + Command Line Interface (dependencies: python-urwid (> 0.9.9)): |
39 | + cd cli |
40 | + ./configure |
41 | + make |
42 | + sudo make install |
43 | |
44 | GNOME (dependencies: python-glade2, python-gnome2, meld): |
45 | cd gnome |
46 | |
47 | === added directory 'cli' |
48 | === added file 'cli/Makefile.template' |
49 | --- cli/Makefile.template 1970-01-01 00:00:00 +0000 |
50 | +++ cli/Makefile.template 2010-03-02 06:06:17 +0000 |
51 | @@ -0,0 +1,25 @@ |
52 | +PREFIX=/usr |
53 | +DEST=$(DESTDIR)$(PREFIX) |
54 | + |
55 | +all: |
56 | + |
57 | +clean: |
58 | + |
59 | +install: |
60 | + #install python |
61 | + install -d $(DEST)/share/backintime/cli |
62 | + install --mode=644 *.py $(DEST)/share/backintime/cli |
63 | + |
64 | + #install copyright file |
65 | + install -d $(DEST)/share/doc/backintime-cli |
66 | + install --mode=644 ../common/debian_specific/copyright $(DEST)/share/doc/backintime-cli |
67 | + |
68 | + #install man file(s) |
69 | + install -d $(DEST)/share/man/man1 |
70 | + install --mode=644 man/C/*.gz $(DEST)/share/man/man1 |
71 | + |
72 | + #install application |
73 | + install -d $(DEST)/bin |
74 | + install backintime-config $(DEST)/bin |
75 | + install backintime-restore $(DEST)/bin |
76 | + |
77 | |
78 | === added file 'cli/backintime-config' |
79 | --- cli/backintime-config 1970-01-01 00:00:00 +0000 |
80 | +++ cli/backintime-config 2010-03-02 06:06:17 +0000 |
81 | @@ -0,0 +1,27 @@ |
82 | +#!/bin/sh |
83 | + |
84 | +# Back In Time |
85 | +# Copyright (C) 2010 Ryan Ahearn |
86 | +# |
87 | +# This program is free software; you can redistribute it and/or modify |
88 | +# it under the terms of the GNU General Public License as published by |
89 | +# the Free Software Foundation; either version 2 of the License, or |
90 | +# (at your option) any later version. |
91 | +# |
92 | +# This program is distributed in the hope that it will be useful, |
93 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
94 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
95 | +# GNU General Public License for more details. |
96 | +# |
97 | +# You should have received a copy of the GNU General Public License along |
98 | +# with this program; if not, write to the Free Software Foundation, Inc., |
99 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
100 | + |
101 | +if [ -f bitconfig.py ]; then |
102 | + APP_PATH="." |
103 | +else |
104 | + APP_PATH="/usr/share/backintime/cli" |
105 | +fi |
106 | + |
107 | +python ${APP_PATH}/bitconfig.py "$@" |
108 | + |
109 | |
110 | === added file 'cli/backintime-restore' |
111 | --- cli/backintime-restore 1970-01-01 00:00:00 +0000 |
112 | +++ cli/backintime-restore 2010-03-02 06:06:17 +0000 |
113 | @@ -0,0 +1,27 @@ |
114 | +#!/bin/sh |
115 | + |
116 | +# Back In Time |
117 | +# Copyright (C) 2010 Ryan Ahearn |
118 | +# |
119 | +# This program is free software; you can redistribute it and/or modify |
120 | +# it under the terms of the GNU General Public License as published by |
121 | +# the Free Software Foundation; either version 2 of the License, or |
122 | +# (at your option) any later version. |
123 | +# |
124 | +# This program is distributed in the hope that it will be useful, |
125 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
126 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
127 | +# GNU General Public License for more details. |
128 | +# |
129 | +# You should have received a copy of the GNU General Public License along |
130 | +# with this program; if not, write to the Free Software Foundation, Inc., |
131 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
132 | + |
133 | +if [ -f bitrestore.py ]; then |
134 | + APP_PATH="." |
135 | +else |
136 | + APP_PATH="/usr/share/backintime/cli" |
137 | +fi |
138 | + |
139 | +python ${APP_PATH}/bitrestore.py "$@" |
140 | + |
141 | |
142 | === added file 'cli/bitconfig.py' |
143 | --- cli/bitconfig.py 1970-01-01 00:00:00 +0000 |
144 | +++ cli/bitconfig.py 2010-03-02 06:06:17 +0000 |
145 | @@ -0,0 +1,142 @@ |
146 | +# Back In Time |
147 | +# Copyright (C) 2010 Ryan Ahearn |
148 | +# |
149 | +# This program is free software; you can redistribute it and/or modify |
150 | +# it under the terms of the GNU General Public License as published by |
151 | +# the Free Software Foundation; either version 2 of the License, or |
152 | +# (at your option) any later version. |
153 | +# |
154 | +# This program is distributed in the hope that it will be useful, |
155 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
156 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
157 | +# GNU General Public License for more details. |
158 | +# |
159 | +# You should have received a copy of the GNU General Public License along |
160 | +# with this program; if not, write to the Free Software Foundation, Inc., |
161 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
162 | + |
163 | + |
164 | +import os.path |
165 | +import sys |
166 | +import urwid |
167 | +import gettext |
168 | + |
169 | +sys.path = [os.path.join( os.path.dirname( os.path.abspath( os.path.dirname( __file__ ) ) ), 'common' )] + sys.path |
170 | + |
171 | +import backintime |
172 | +import config |
173 | +import logger |
174 | +import guiapplicationinstance |
175 | +import profilewidget |
176 | +import generalwidget |
177 | +import includewidget |
178 | +import excludewidget |
179 | +import removewidget |
180 | +import optionswidget |
181 | +import expertwidget |
182 | + |
183 | +_=gettext.gettext |
184 | + |
185 | +class MainWindow(object): |
186 | + |
187 | + def __init__( self, config ): |
188 | + self._config = config |
189 | + |
190 | + self._header = _('Back in Time Configuration') + '. ' + _('F6 exits') |
191 | + setting_sections = [ "Profiles", "General", "Include", "Exclude", "Auto-remove", "Options", "Expert Options" ] |
192 | + self._listbox_content = [ |
193 | + urwid.Divider(), # position 0 |
194 | + urwid.Text( _("Profile") + ": " + config.get_profile_name() ), # position 1 |
195 | + urwid.Divider(), # position 2 |
196 | + urwid.GridFlow( [ urwid.AttrWrap( urwid.Button( _(txt), self.sections_button_press, txt ), 'button', 'button_focus' ) for txt in setting_sections ], |
197 | + 18, 2, 1, 'center' ), # position 3 |
198 | + urwid.Divider(), # position 4 |
199 | + profilewidget.ProfileWidget( self, config ), # position 5 |
200 | + ] |
201 | + |
202 | + def sections_button_press( self, button, user_data ): |
203 | + if user_data == 'Profiles': |
204 | + widget = profilewidget.ProfileWidget( self, self._config ) |
205 | + elif user_data == 'General': |
206 | + widget = generalwidget.GeneralWidget( self, self._config ) |
207 | + elif user_data == 'Include': |
208 | + widget = includewidget.IncludeWidget( self, self._config ) |
209 | + elif user_data == 'Exclude': |
210 | + widget = excludewidget.ExcludeWidget( self, self._config ) |
211 | + elif user_data == 'Auto-remove': |
212 | + widget = removewidget.RemoveWidget( self._config ) |
213 | + elif user_data == 'Options': |
214 | + widget = optionswidget.OptionsWidget( self._config ) |
215 | + elif user_data == 'Expert Options': |
216 | + widget = expertwidget.ExpertOptionsWidget( self._config ) |
217 | + self.update_content( widget, 5 ) |
218 | + |
219 | + def show( self ): |
220 | + header = urwid.AttrWrap( urwid.Text( self._header, align='center' ), 'header' ) |
221 | + self._content = urwid.SimpleListWalker( self._listbox_content ) |
222 | + self._listbox = urwid.ListBox( self._content ) |
223 | + frame = urwid.Frame( urwid.AttrWrap( self._listbox, 'body' ), header=header ) |
224 | + |
225 | + palette = [ |
226 | + ( 'body', 'black', 'light gray', 'standout' ), |
227 | + ( 'error', 'dark red', 'light gray', 'bold' ), |
228 | + ( 'header', 'white', 'dark red', 'bold' ), |
229 | + ( 'button', 'black', 'dark cyan' ), |
230 | + ( 'button_focus', 'white', 'dark blue', 'bold' ), |
231 | + ( 'edit_box', 'light gray', 'dark blue' ), |
232 | + ( 'edit_focus', 'white', 'dark blue', 'bold' ) |
233 | + ] |
234 | + |
235 | + urwid.MainLoop( frame, palette, unhandled_input=self.unhandled_input ).run() |
236 | + |
237 | + def update_content( self, widget, position ): |
238 | + self._content[position] = widget |
239 | + |
240 | + def update_profile_name( self ): |
241 | + self.update_content( urwid.Text( _('Profile') + ': ' + self._config.get_profile_name() ), 1 ) |
242 | + |
243 | + def unhandled_input( self, key ): |
244 | + if key == 'f6': |
245 | + self.on_close() |
246 | + |
247 | + def on_close( self ): |
248 | + self.update_content( ConfirmSave( self._config ), 5 ) |
249 | + |
250 | +class ConfirmSave(urwid.WidgetWrap): |
251 | + |
252 | + def __init__( self, config ): |
253 | + self._config = config |
254 | + |
255 | + pile_list = [ |
256 | + urwid.Padding( urwid.Text( _('Save configuration?') ), 'center' ), |
257 | + urwid.Divider(), |
258 | + urwid.GridFlow( [ |
259 | + urwid.AttrWrap( urwid.Button( _('Yes'), self.save ), 'button', 'button_focus' ), |
260 | + urwid.AttrWrap( urwid.Button( _('No'), self.close ), 'button', 'button_focus' ) |
261 | + ], 10, 2, 1, 'center' ) |
262 | + ] |
263 | + |
264 | + display_widget = urwid.Pile( pile_list ) |
265 | + urwid.WidgetWrap.__init__( self, display_widget ) |
266 | + |
267 | + def save( self, button ): |
268 | + self._config.save() |
269 | + self._config.setup_cron() |
270 | + self.close() |
271 | + |
272 | + def close( self, button=None ): |
273 | + raise urwid.ExitMainLoop() |
274 | + |
275 | +if __name__ == '__main__': |
276 | + cfg = backintime.start_app( 'backintime-config' ) |
277 | + raise_cmd = '' |
278 | + if len( sys.argv ) > 1: |
279 | + raise_cmd = '\n'.join( sys.argv[ 1 : ] ) |
280 | + app_instance = guiapplicationinstance.GUIApplicationInstance( cfg.get_app_instance_file(), raise_cmd ) |
281 | + |
282 | + logger.openlog() |
283 | + main_window = MainWindow( cfg ) |
284 | + main_window.show() |
285 | + logger.closelog() |
286 | + |
287 | + app_instance.exit_application() |
288 | |
289 | === added file 'cli/bitrestore.py' |
290 | --- cli/bitrestore.py 1970-01-01 00:00:00 +0000 |
291 | +++ cli/bitrestore.py 2010-03-02 06:06:17 +0000 |
292 | @@ -0,0 +1,131 @@ |
293 | +# Back In Time |
294 | +# Copyright (C) 2010 Ryan Ahearn |
295 | +# |
296 | +# This program is free software; you can redistribute it and/or modify |
297 | +# it under the terms of the GNU General Public License as published by |
298 | +# the Free Software Foundation; either version 2 of the License, or |
299 | +# (at your option) any later version. |
300 | +# |
301 | +# This program is distributed in the hope that it will be useful, |
302 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
303 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
304 | +# GNU General Public License for more details. |
305 | +# |
306 | +# You should have received a copy of the GNU General Public License along |
307 | +# with this program; if not, write to the Free Software Foundation, Inc., |
308 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
309 | + |
310 | + |
311 | +import os.path |
312 | +import sys |
313 | +import urwid |
314 | +import gettext |
315 | + |
316 | +sys.path = [os.path.join( os.path.dirname( os.path.abspath( os.path.dirname( __file__ ) ) ), 'common' )] + sys.path |
317 | + |
318 | +import backintime |
319 | +import config |
320 | +import logger |
321 | +import guiapplicationinstance |
322 | +import profilewidget |
323 | +import restorewidget |
324 | +import removesnapshot |
325 | +import snapshotname |
326 | + |
327 | +_=gettext.gettext |
328 | + |
329 | +class MainWindow(object): |
330 | + |
331 | + def __init__( self, config ): |
332 | + self._config = config |
333 | + self.selected_snapshot = '' |
334 | + self.selected_snapshot_name = '' |
335 | + self.current_directory = config.get_str_value( 'cli.last_path', '/' ) |
336 | + self.show_hidden = False |
337 | + |
338 | + self._header = _('Back in Time Restore Utility') + '. ' + _('F6 exits') |
339 | + self._profile_button = urwid.Button( config.get_profile_name(), self.change_profile ) |
340 | + buttons = [ 'Take Snapshot', 'Update Snapshots', 'Snapshot Name', 'Remove Snapshot' ] |
341 | + self._listbox_content = [ |
342 | + urwid.Divider(), # position 0 |
343 | + urwid.AttrWrap( self._profile_button, 'button', 'button_focus' ), # position 1 |
344 | + urwid.Divider(), # position 2 |
345 | + urwid.GridFlow( [ urwid.AttrWrap( urwid.Button( _(txt), self.button_press, txt ), 'button', 'button_focus' ) for txt in buttons ], |
346 | + 20, 2, 1, 'center' ), # position 3 |
347 | + urwid.Divider(), # position 4 |
348 | + restorewidget.RestoreWidget( self, config ), # position 5 |
349 | + ] |
350 | + |
351 | + def change_profile( self, button ): |
352 | + self.update_content( profilewidget.ProfileWidget( self, self._config, False ), 5 ) |
353 | + |
354 | + def button_press( self, button, user_data ): |
355 | + if user_data == 'Take Snapshot': |
356 | + backintime.take_snapshot_now_async( self._config ) |
357 | + elif user_data == 'Update Snapshots': |
358 | + self.update_content( restorewidget.RestoreWidget( self, self._config ), 5 ) |
359 | + elif user_data == 'Snapshot Name' and self.selected_snapshot != '': |
360 | + self.update_content( snapshotname.SnapshotName( self, self._config ), 5 ) |
361 | + elif user_data == 'Remove Snapshot' and self.selected_snapshot != '': |
362 | + self.update_content( removesnapshot.RemoveSnapshot( self, self._config ), 5 ) |
363 | + |
364 | + def show( self ): |
365 | + header = urwid.AttrWrap( urwid.Text( self._header, align='center' ), 'header' ) |
366 | + self._content = urwid.SimpleListWalker( self._listbox_content ) |
367 | + self._listbox = urwid.ListBox( self._content ) |
368 | + frame = urwid.Frame( urwid.AttrWrap( self._listbox, 'body' ), header=header ) |
369 | + |
370 | + palette = [ |
371 | + ( 'body', 'black', 'light gray', 'standout' ), |
372 | + ( 'error', 'dark red', 'light gray', 'bold' ), |
373 | + ( 'header', 'white', 'dark red', 'bold' ), |
374 | + ( 'button', 'black', 'dark cyan' ), |
375 | + ( 'button_focus', 'white', 'dark blue', 'bold' ), |
376 | + ( 'edit_box', 'light gray', 'dark blue' ), |
377 | + ( 'edit_focus', 'white', 'dark blue', 'bold' ) |
378 | + ] |
379 | + |
380 | + self.main_loop = urwid.MainLoop( frame, palette, unhandled_input=self.unhandled_input ) |
381 | + self.main_loop.run() |
382 | + |
383 | + def update_content( self, widget, position ): |
384 | + self._content[position] = widget |
385 | + |
386 | + def update_profile_name( self ): |
387 | + self._profile_button.set_label( self._config.get_profile_name() ) |
388 | + self.selected_snapshot = '' |
389 | + self.update_content( restorewidget.RestoreWidget( self, self._config ), 5 ) |
390 | + |
391 | + def update_current_directory( self, new_directory ): |
392 | + self.current_directory = new_directory |
393 | + self._config.set_str_value( 'cli.last_path', new_directory ) |
394 | + self.update_content( restorewidget.RestoreWidget( self, self._config ), 5 ) |
395 | + |
396 | + def is_selected_snapshot( self, snapshot ): |
397 | + if self.selected_snapshot == snapshot: |
398 | + return True |
399 | + else: |
400 | + return False |
401 | + |
402 | + def unhandled_input( self, key ): |
403 | + if key == 'f6': |
404 | + self.on_close() |
405 | + |
406 | + def on_close( self ): |
407 | + self._config.save() |
408 | + raise urwid.ExitMainLoop() |
409 | + |
410 | + |
411 | +if __name__ == '__main__': |
412 | + cfg = backintime.start_app( 'backintime-restore' ) |
413 | + raise_cmd = '' |
414 | + if len( sys.argv ) > 1: |
415 | + raise_cmd = '\n'.join( sys.argv[ 1 : ] ) |
416 | + app_instance = guiapplicationinstance.GUIApplicationInstance( cfg.get_app_instance_file(), raise_cmd ) |
417 | + |
418 | + logger.openlog() |
419 | + main_window = MainWindow( cfg ) |
420 | + main_window.show() |
421 | + logger.closelog() |
422 | + |
423 | + app_instance.exit_application() |
424 | |
425 | === added file 'cli/configure' |
426 | --- cli/configure 1970-01-01 00:00:00 +0000 |
427 | +++ cli/configure 2010-03-02 06:06:17 +0000 |
428 | @@ -0,0 +1,12 @@ |
429 | +#!/bin/bash |
430 | + |
431 | +if [ -e Makefile ]; then |
432 | + rm Makefile; |
433 | +fi |
434 | + |
435 | +cp Makefile.template Makefile |
436 | + |
437 | +echo "All OK. Now run:" |
438 | +echo " make" |
439 | +echo " sudo make install" |
440 | + |
441 | |
442 | === added file 'cli/copywidget.py' |
443 | --- cli/copywidget.py 1970-01-01 00:00:00 +0000 |
444 | +++ cli/copywidget.py 2010-03-02 06:06:17 +0000 |
445 | @@ -0,0 +1,67 @@ |
446 | +# Back In Time |
447 | +# Copyright (C) 2010 Ryan Ahearn |
448 | +# |
449 | +# This program is free software; you can redistribute it and/or modify |
450 | +# it under the terms of the GNU General Public License as published by |
451 | +# the Free Software Foundation; either version 2 of the License, or |
452 | +# (at your option) any later version. |
453 | +# |
454 | +# This program is distributed in the hope that it will be useful, |
455 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
456 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
457 | +# GNU General Public License for more details. |
458 | +# |
459 | +# You should have received a copy of the GNU General Public License along |
460 | +# with this program; if not, write to the Free Software Foundation, Inc., |
461 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
462 | + |
463 | + |
464 | +import os.path |
465 | +import shutil |
466 | +import urwid |
467 | +import gettext |
468 | + |
469 | +import logger |
470 | +import restorewidget |
471 | + |
472 | +_=gettext.gettext |
473 | + |
474 | +class CopyWidget(urwid.WidgetWrap): |
475 | + |
476 | + def __init__( self, main_win, config, to_copy ): |
477 | + self._main_win = main_win |
478 | + self._config = config |
479 | + self._to_copy = to_copy |
480 | + |
481 | + self._edit_box = urwid.Edit(( 'body', _('Enter destination') + ': ' )) |
482 | + pile_list = [ |
483 | + urwid.AttrWrap( self._edit_box, 'edit_box', 'edit_focus' ), |
484 | + urwid.Divider(), |
485 | + urwid.GridFlow( [ |
486 | + urwid.AttrWrap( urwid.Button( _('OK'), self.ok_pressed ), 'button', 'button_focus' ), |
487 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.go_home ), 'button', 'button_focus' ) |
488 | + ], 10, 2, 1, 'right' ) |
489 | + ] |
490 | + |
491 | + display_widget = urwid.Pile( pile_list ) |
492 | + urwid.WidgetWrap.__init__( self, display_widget ) |
493 | + |
494 | + def ok_pressed( self, button ): |
495 | + destination = self._edit_box.get_edit_text().strip() |
496 | + logger.info( 'copying %s to %s' % ( self._to_copy, destination ) ) |
497 | + if os.path.isdir( self._to_copy ): |
498 | + self._copy_directory( destination ) |
499 | + else: |
500 | + self._copy_file( destination ) |
501 | + self.go_home() |
502 | + |
503 | + def _copy_directory( self, destination ): |
504 | + while os.path.exists( destination ): |
505 | + destination = os.path.join( destination, os.path.basename( self._to_copy ) ) |
506 | + shutil.copytree( self._to_copy, destination, True ) |
507 | + |
508 | + def _copy_file( self, destination ): |
509 | + shutil.copy2( self._to_copy, destination ) |
510 | + |
511 | + def go_home( self, button=None ): |
512 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
513 | |
514 | === added directory 'cli/debian_specific' |
515 | === added file 'cli/debian_specific/control' |
516 | --- cli/debian_specific/control 1970-01-01 00:00:00 +0000 |
517 | +++ cli/debian_specific/control 2010-03-02 06:06:17 +0000 |
518 | @@ -0,0 +1,10 @@ |
519 | +Package: backintime-cli |
520 | +Version: 0.9.99.18 |
521 | +Priority: optional |
522 | +Section: utils |
523 | +Maintainer: BIT Team <bit-team@lists.launchpad.net> |
524 | +Architecture: all |
525 | +Homepage: http://backintime.le-web.org |
526 | +Depends: python-urwid (>> 0.9.9), backintime-common (= 0.9.99.18) |
527 | +Description: Simple backup system for command line use. |
528 | + This is a command line interface frontend for backintime-common. |
529 | |
530 | === added file 'cli/debian_specific/control.source' |
531 | --- cli/debian_specific/control.source 1970-01-01 00:00:00 +0000 |
532 | +++ cli/debian_specific/control.source 2010-03-02 06:06:17 +0000 |
533 | @@ -0,0 +1,14 @@ |
534 | +Source: backintime-cli |
535 | +Maintainer: BIT Team <bit-team@lists.launchpad.net> |
536 | +Section: utils |
537 | +Priority: optional |
538 | +Standards-Version: 3.7.3 |
539 | +Homepage: http://backintime.le-web.org |
540 | + |
541 | +Package: backintime-cli |
542 | +Architecture: all |
543 | +Section: utils |
544 | +Priority: optional |
545 | +Depends: python-urwid (>> 0.9.9), backintime-common (= 0.9.99.18) |
546 | +Description: Simple backup system for command line use. |
547 | + This is a command line interface frontend for backintime-common. |
548 | |
549 | === added file 'cli/debian_specific/postrm' |
550 | --- cli/debian_specific/postrm 1970-01-01 00:00:00 +0000 |
551 | +++ cli/debian_specific/postrm 2010-03-02 06:06:17 +0000 |
552 | @@ -0,0 +1,3 @@ |
553 | +#!/bin/sh |
554 | +rm -rf /usr/share/backintime/cli/*.pyc |
555 | +exit 0 |
556 | |
557 | === added file 'cli/debian_specific/rules' |
558 | --- cli/debian_specific/rules 1970-01-01 00:00:00 +0000 |
559 | +++ cli/debian_specific/rules 2010-03-02 06:06:17 +0000 |
560 | @@ -0,0 +1,50 @@ |
561 | +#!/usr/bin/make -f |
562 | + |
563 | +package = backintime-cli |
564 | + |
565 | +clean: |
566 | + dh_testdir |
567 | + dh_clean |
568 | + rm -f build |
569 | + |
570 | +install: build |
571 | + #install python |
572 | + #dh_installdirs /usr/share/backintime/gnome |
573 | + dh_install *.py /usr/share/backintime/cli |
574 | + |
575 | + #install copyright file |
576 | + #dh_installdirs /usr/share/doc/backintime-gnome |
577 | + dh_install debian/copyright /usr/share/doc/backintime-cli |
578 | + |
579 | + #install man file(s) |
580 | + #dh_installdirs /usr/share/man/man1 |
581 | + dh_install man/C/*.gz /usr/share/man/man1 |
582 | + |
583 | + #install application |
584 | + #dh_installdirs /usr/bin |
585 | + dh_install backintime-config /usr/bin |
586 | + dh_install backintime-restore /usr/bin |
587 | + |
588 | +build: |
589 | + touch build |
590 | + |
591 | +binary-indep: install |
592 | + dh_testdir -i |
593 | + dh_testroot -i |
594 | + #dh_installdocs -i NEWS |
595 | + #dh_installchangelogs -i ChangeLog |
596 | + #dh_strip -i |
597 | + #dh_compress -i |
598 | + dh_fixperms -i |
599 | + dh_installdeb -i |
600 | + #dh_shlibdeps -i |
601 | + dh_gencontrol -i |
602 | + dh_md5sums -i |
603 | + dh_builddeb -i |
604 | + |
605 | +binary-arch: install |
606 | + |
607 | +binary: binary-indep |
608 | + |
609 | +.PHONY: binary binary-arch binary-indep clean |
610 | + |
611 | |
612 | === added file 'cli/excludewidget.py' |
613 | --- cli/excludewidget.py 1970-01-01 00:00:00 +0000 |
614 | +++ cli/excludewidget.py 2010-03-02 06:06:17 +0000 |
615 | @@ -0,0 +1,118 @@ |
616 | +# Back In Time |
617 | +# Copyright (C) 2010 Ryan Ahearn |
618 | +# |
619 | +# This program is free software; you can redistribute it and/or modify |
620 | +# it under the terms of the GNU General Public License as published by |
621 | +# the Free Software Foundation; either version 2 of the License, or |
622 | +# (at your option) any later version. |
623 | +# |
624 | +# This program is distributed in the hope that it will be useful, |
625 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
626 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
627 | +# GNU General Public License for more details. |
628 | +# |
629 | +# You should have received a copy of the GNU General Public License along |
630 | +# with this program; if not, write to the Free Software Foundation, Inc., |
631 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
632 | + |
633 | +import urwid |
634 | +import gettext |
635 | + |
636 | +import logger |
637 | + |
638 | +_=gettext.gettext |
639 | + |
640 | +class ExcludeWidget(urwid.WidgetWrap): |
641 | + |
642 | + def __init__( self, main_win, config ): |
643 | + self._main_win = main_win |
644 | + self._config = config |
645 | + self._to_delete = None |
646 | + |
647 | + all_patterns = config.get_exclude_patterns() |
648 | + if len( all_patterns ) == 0: |
649 | + chooser = urwid.Divider() |
650 | + else: |
651 | + excluded_patterns = [] |
652 | + for pattern in all_patterns: |
653 | + urwid.RadioButton( excluded_patterns, pattern, False, self.pattern_selected ) |
654 | + chooser = urwid.Pile( excluded_patterns ) |
655 | + |
656 | + pile_list = [ |
657 | + urwid.Text( _('Patterns, files or folders') ), |
658 | + urwid.Divider(), |
659 | + chooser, |
660 | + urwid.Divider(), |
661 | + urwid.GridFlow([ |
662 | + urwid.AttrWrap( urwid.Button( _('Add'), self.add_pattern ), 'button', 'button_focus' ), |
663 | + urwid.AttrWrap( urwid.Button( _('Delete'), self.delete_pattern ), 'button', 'button_focus' ), |
664 | + ], 10, 2, 1, 'center' ) |
665 | + ] |
666 | + |
667 | + display_widget = urwid.Pile( pile_list ) |
668 | + urwid.WidgetWrap.__init__( self, display_widget ) |
669 | + |
670 | + def pattern_selected( self, button, new_state ): |
671 | + if new_state: |
672 | + self._to_delete = button.get_label() |
673 | + |
674 | + def add_pattern( self, button ): |
675 | + self._main_win.update_content( AddExcludeWidget( self._main_win, self._config ), 5 ) |
676 | + |
677 | + def delete_pattern( self, button ): |
678 | + if self._to_delete is not None: |
679 | + self._main_win.update_content( DeleteExcludeWidget( self._main_win, self._config, self._to_delete ), 5 ) |
680 | + |
681 | + def go_to_exclude_patterns( self, button=None ): |
682 | + self._main_win.update_content( ExcludeWidget( self._main_win, self._config ), 5 ) |
683 | + |
684 | + |
685 | +class AddExcludeWidget(ExcludeWidget): |
686 | + |
687 | + def __init__( self, main_win, config ): |
688 | + self._main_win = main_win |
689 | + self._config = config |
690 | + |
691 | + self._edit_box = urwid.Edit(( 'body', _('Enter pattern, file, or folder to exclude') + ': ' )) |
692 | + pile_list = [ |
693 | + urwid.AttrWrap( self._edit_box, 'edit_box', 'edit_focus' ), |
694 | + urwid.Divider(), |
695 | + urwid.GridFlow( [ |
696 | + urwid.AttrWrap( urwid.Button( _('OK'), self.ok_pressed ), 'button', 'button_focus' ), |
697 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.go_to_exclude_patterns ), 'button', 'button_focus' ) |
698 | + ], 10, 2, 1, 'right' ) |
699 | + ] |
700 | + |
701 | + display_widget = urwid.Pile( pile_list ) |
702 | + urwid.WidgetWrap.__init__( self, display_widget ) |
703 | + |
704 | + def ok_pressed( self, button ): |
705 | + all_patterns = self._config.get_exclude_patterns() |
706 | + all_patterns.append( self._edit_box.get_edit_text().strip() ) |
707 | + self._config.set_exclude_patterns( all_patterns ) |
708 | + self.go_to_exclude_patterns() |
709 | + |
710 | +class DeleteExcludeWidget(ExcludeWidget): |
711 | + |
712 | + def __init__( self, main_win, config, to_delete ): |
713 | + self._main_win = main_win |
714 | + self._config = config |
715 | + self._to_delete = to_delete |
716 | + |
717 | + pile_list = [ |
718 | + urwid.Text( _('Are you sure you want to remove') + ' "' + to_delete + '" ' + _('from the excluded patterns?') ), |
719 | + urwid.Divider(), |
720 | + urwid.GridFlow( [ |
721 | + urwid.AttrWrap( urwid.Button( _('Yes'), self.yes_pressed ), 'button', 'button_focus' ), |
722 | + urwid.AttrWrap( urwid.Button( _('No'), self.go_to_exclude_patterns ), 'button', 'button_focus' ) |
723 | + ], 10, 2, 1, 'right' ) |
724 | + ] |
725 | + |
726 | + display_widget = urwid.Pile( pile_list ) |
727 | + urwid.WidgetWrap.__init__( self, display_widget ) |
728 | + |
729 | + def yes_pressed( self, button ): |
730 | + all_patterns = self._config.get_exclude_patterns() |
731 | + all_patterns.remove( self._to_delete ) |
732 | + self._config.set_exclude_patterns( all_patterns ) |
733 | + self.go_to_exclude_patterns() |
734 | |
735 | === added file 'cli/expertwidget.py' |
736 | --- cli/expertwidget.py 1970-01-01 00:00:00 +0000 |
737 | +++ cli/expertwidget.py 2010-03-02 06:06:17 +0000 |
738 | @@ -0,0 +1,47 @@ |
739 | +# Back In Time |
740 | +# Copyright (C) 2010 Ryan Ahearn |
741 | +# |
742 | +# This program is free software; you can redistribute it and/or modify |
743 | +# it under the terms of the GNU General Public License as published by |
744 | +# the Free Software Foundation; either version 2 of the License, or |
745 | +# (at your option) any later version. |
746 | +# |
747 | +# This program is distributed in the hope that it will be useful, |
748 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
749 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
750 | +# GNU General Public License for more details. |
751 | +# |
752 | +# You should have received a copy of the GNU General Public License along |
753 | +# with this program; if not, write to the Free Software Foundation, Inc., |
754 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
755 | + |
756 | +import urwid |
757 | +import gettext |
758 | + |
759 | +import logger |
760 | + |
761 | +_=gettext.gettext |
762 | + |
763 | +class ExpertOptionsWidget(urwid.WidgetWrap): |
764 | + |
765 | + def __init__( self, config ): |
766 | + self._config = config |
767 | + |
768 | + pile_list = [ |
769 | + urwid.Padding( urwid.Text(( 'error', _('Change these options only if you really know what you are doing!') )), 'center' ), |
770 | + urwid.Divider(), |
771 | + urwid.CheckBox( _("Run 'nice' as cron job (default: enabled)"), config.is_run_nice_from_cron_enabled(), on_state_change=self.flip_nice_cron ), |
772 | + urwid.CheckBox( _("Run 'ionice' as cron job (default: enabled)"), config.is_run_ionice_from_cron_enabled(), on_state_change=self.flip_ionice_cron ), |
773 | + urwid.CheckBox( _("Run 'ionice' when taking a manual snapshot (default: disabled)"), config.is_run_ionice_from_user_enabled(), on_state_change=self.flip_ionice_user ) |
774 | + ] |
775 | + display_widget = urwid.Pile( pile_list ) |
776 | + urwid.WidgetWrap.__init__( self, display_widget ) |
777 | + |
778 | + def flip_nice_cron( self, check_box, new_state ): |
779 | + self._config.set_run_nice_from_cron_enabled( new_state ) |
780 | + |
781 | + def flip_ionice_cron( self, check_box, new_state ): |
782 | + self._config.set_run_ionice_from_cron_enabled( new_state ) |
783 | + |
784 | + def flip_ionice_user( self, check_box, new_state ): |
785 | + self._config.set_run_ionice_from_user_enabled( new_state ) |
786 | |
787 | === added file 'cli/generalwidget.py' |
788 | --- cli/generalwidget.py 1970-01-01 00:00:00 +0000 |
789 | +++ cli/generalwidget.py 2010-03-02 06:06:17 +0000 |
790 | @@ -0,0 +1,93 @@ |
791 | +# Back In Time |
792 | +# Copyright (C) 2010 Ryan Ahearn |
793 | +# |
794 | +# This program is free software; you can redistribute it and/or modify |
795 | +# it under the terms of the GNU General Public License as published by |
796 | +# the Free Software Foundation; either version 2 of the License, or |
797 | +# (at your option) any later version. |
798 | +# |
799 | +# This program is distributed in the hope that it will be useful, |
800 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
801 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
802 | +# GNU General Public License for more details. |
803 | +# |
804 | +# You should have received a copy of the GNU General Public License along |
805 | +# with this program; if not, write to the Free Software Foundation, Inc., |
806 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
807 | + |
808 | +import urwid |
809 | +import gettext |
810 | + |
811 | +import logger |
812 | + |
813 | +_=gettext.gettext |
814 | + |
815 | +class GeneralWidget(urwid.WidgetWrap): |
816 | + |
817 | + def __init__( self, main_win, config ): |
818 | + self._config = config |
819 | + self._main_win = main_win |
820 | + |
821 | + backup_mode = config.get_automatic_backup_mode() |
822 | + backup_modes = [] |
823 | + for key, value in sorted( config.AUTOMATIC_BACKUP_MODES.items() ): |
824 | + if backup_mode == key: |
825 | + urwid.RadioButton( backup_modes, value, True, self.schedule_changed, key ) |
826 | + else: |
827 | + urwid.RadioButton( backup_modes, value, False, self.schedule_changed, key ) |
828 | + schedule_chooser = urwid.Pile( backup_modes ) |
829 | + |
830 | + location = urwid.Edit(( 'body', _('Where to save snapshots') + ': ' ), config.get_snapshots_path() ) |
831 | + urwid.connect_signal( location, 'change', self.location_changed ) |
832 | + self._error = urwid.Text( '' ) |
833 | + pile_list = [ |
834 | + urwid.AttrWrap( location, 'edit_box', 'edit_focus' ), |
835 | + urwid.AttrWrap( self._error, 'error' ), |
836 | + urwid.Divider() |
837 | + ] |
838 | + |
839 | + if backup_mode > config.HOUR: |
840 | + # display chooser to set hour of the day to run the cron job |
841 | + set_hour = config.get_automatic_backup_time() / 100 |
842 | + hour_choices = [] |
843 | + for i in range( 24 ): |
844 | + if set_hour == i: |
845 | + urwid.RadioButton( hour_choices, ( "%2d:00" % i ), True, self.time_changed, i ) |
846 | + else: |
847 | + urwid.RadioButton( hour_choices, ( "%2d:00" % i ), False, self.time_changed, i ) |
848 | + hour_chooser = urwid.Pile( hour_choices ) |
849 | + pile_list.append( |
850 | + urwid.Columns( [ |
851 | + urwid.Pile( [ |
852 | + urwid.Text( _('Schedule') ), |
853 | + schedule_chooser |
854 | + ] ), |
855 | + urwid.Pile( [ |
856 | + urwid.Text( _('Hour') ), |
857 | + hour_chooser |
858 | + ] ) |
859 | + ], 1 ) |
860 | + ) |
861 | + else: |
862 | + pile_list.extend( [ |
863 | + urwid.Text( _('Schedule') ), |
864 | + schedule_chooser |
865 | + ] ) |
866 | + |
867 | + display_widget = urwid.Pile( pile_list ) |
868 | + urwid.WidgetWrap.__init__( self, display_widget ) |
869 | + |
870 | + def schedule_changed( self, check_box, new_state, user_data ): |
871 | + if new_state: |
872 | + self._config.set_automatic_backup_mode( user_data ) |
873 | + self._main_win.update_content( GeneralWidget( self._main_win, self._config ), 5 ) |
874 | + |
875 | + def time_changed( self, check_box, new_state, user_data ): |
876 | + if new_state: |
877 | + self._config.set_automatic_backup_time( user_data * 100 ) |
878 | + |
879 | + def location_changed( self, edit, new_edit_text ): |
880 | + if not self._config.set_snapshots_path( new_edit_text.strip() ): |
881 | + self._error.set_text( _('Could not use this path, are you sure it exists and you have write access?') ) |
882 | + else: |
883 | + self._error.set_text( '' ) |
884 | |
885 | === added file 'cli/includewidget.py' |
886 | --- cli/includewidget.py 1970-01-01 00:00:00 +0000 |
887 | +++ cli/includewidget.py 2010-03-02 06:06:17 +0000 |
888 | @@ -0,0 +1,118 @@ |
889 | +# Back In Time |
890 | +# Copyright (C) 2010 Ryan Ahearn |
891 | +# |
892 | +# This program is free software; you can redistribute it and/or modify |
893 | +# it under the terms of the GNU General Public License as published by |
894 | +# the Free Software Foundation; either version 2 of the License, or |
895 | +# (at your option) any later version. |
896 | +# |
897 | +# This program is distributed in the hope that it will be useful, |
898 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
899 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
900 | +# GNU General Public License for more details. |
901 | +# |
902 | +# You should have received a copy of the GNU General Public License along |
903 | +# with this program; if not, write to the Free Software Foundation, Inc., |
904 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
905 | + |
906 | +import urwid |
907 | +import gettext |
908 | + |
909 | +import logger |
910 | + |
911 | +_=gettext.gettext |
912 | + |
913 | +class IncludeWidget(urwid.WidgetWrap): |
914 | + |
915 | + def __init__( self, main_win, config ): |
916 | + self._main_win = main_win |
917 | + self._config = config |
918 | + self._to_delete = None |
919 | + |
920 | + all_folders = config.get_include_folders() |
921 | + if len( all_folders ) == 0: |
922 | + chooser = urwid.Divider() |
923 | + else: |
924 | + included_folders = [] |
925 | + for folder in all_folders: |
926 | + urwid.RadioButton( included_folders, folder, False, self.folder_selected ) |
927 | + chooser = urwid.Pile( included_folders ) |
928 | + |
929 | + pile_list = [ |
930 | + urwid.Text( _('Include Folders') ), |
931 | + urwid.Divider(), |
932 | + chooser, |
933 | + urwid.Divider(), |
934 | + urwid.GridFlow( [ |
935 | + urwid.AttrWrap( urwid.Button( _('Add'), self.add_folder ), 'button', 'button_focus' ), |
936 | + urwid.AttrWrap( urwid.Button( _('Delete'), self.delete_folder ), 'button', 'button_focus' ), |
937 | + ], 10, 2, 1, 'center' ) |
938 | + ] |
939 | + |
940 | + display_widget = urwid.Pile( pile_list ) |
941 | + urwid.WidgetWrap.__init__( self, display_widget ) |
942 | + |
943 | + def folder_selected( self, button, new_state ): |
944 | + if new_state: |
945 | + self._to_delete = button.get_label() |
946 | + |
947 | + def add_folder( self, button ): |
948 | + self._main_win.update_content( AddIncludeWidget( self._main_win, self._config ), 5 ) |
949 | + |
950 | + def delete_folder( self, button ): |
951 | + if self._to_delete is not None: |
952 | + self._main_win.update_content( DeleteIncludeWidget( self._main_win, self._config, self._to_delete ), 5 ) |
953 | + |
954 | + def go_to_include_folders( self, button=None ): |
955 | + self._main_win.update_content( IncludeWidget( self._main_win, self._config ), 5 ) |
956 | + |
957 | + |
958 | +class AddIncludeWidget(IncludeWidget): |
959 | + |
960 | + def __init__( self, main_win, config ): |
961 | + self._main_win = main_win |
962 | + self._config = config |
963 | + |
964 | + self._edit_box = urwid.Edit(( 'body', _('Enter path for folder to backup') + ': ' )) |
965 | + pile_list = [ |
966 | + urwid.AttrWrap( self._edit_box, 'edit_box', 'edit_focus' ), |
967 | + urwid.Divider(), |
968 | + urwid.GridFlow( [ |
969 | + urwid.AttrWrap( urwid.Button( _('OK'), self.ok_pressed ), 'button', 'button_focus' ), |
970 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.go_to_include_folders ), 'button', 'button_focus' ) |
971 | + ], 10, 2, 1, 'right' ) |
972 | + ] |
973 | + |
974 | + display_widget = urwid.Pile( pile_list ) |
975 | + urwid.WidgetWrap.__init__( self, display_widget ) |
976 | + |
977 | + def ok_pressed( self, button ): |
978 | + all_folders = self._config.get_include_folders() |
979 | + all_folders.append( self._edit_box.get_edit_text().strip() ) |
980 | + self._config.set_include_folders( all_folders ) |
981 | + self.go_to_include_folders() |
982 | + |
983 | +class DeleteIncludeWidget(IncludeWidget): |
984 | + |
985 | + def __init__( self, main_win, config, to_delete ): |
986 | + self._main_win = main_win |
987 | + self._config = config |
988 | + self._to_delete = to_delete |
989 | + |
990 | + pile_list = [ |
991 | + urwid.Text( _('Are you sure you want to remove') + ' "' + to_delete + '" ' + _('from the backed up folders?') ), |
992 | + urwid.Divider(), |
993 | + urwid.GridFlow( [ |
994 | + urwid.AttrWrap( urwid.Button( _('Yes'), self.yes_pressed ), 'button', 'button_focus' ), |
995 | + urwid.AttrWrap( urwid.Button( _('No'), self.go_to_include_folders ), 'button', 'button_focus' ) |
996 | + ], 10, 2, 1, 'right' ) |
997 | + ] |
998 | + |
999 | + display_widget = urwid.Pile( pile_list ) |
1000 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1001 | + |
1002 | + def yes_pressed( self, button ): |
1003 | + all_folders = self._config.get_include_folders() |
1004 | + all_folders.remove( self._to_delete ) |
1005 | + self._config.set_include_folders( all_folders ) |
1006 | + self.go_to_include_folders() |
1007 | |
1008 | === added directory 'cli/man' |
1009 | === added directory 'cli/man/C' |
1010 | === added file 'cli/man/C/backintime-config.1.gz' |
1011 | Binary files cli/man/C/backintime-config.1.gz 1970-01-01 00:00:00 +0000 and cli/man/C/backintime-config.1.gz 2010-03-02 06:06:18 +0000 differ |
1012 | === added file 'cli/man/C/backintime-restore.1.gz' |
1013 | Binary files cli/man/C/backintime-restore.1.gz 1970-01-01 00:00:00 +0000 and cli/man/C/backintime-restore.1.gz 2010-03-02 06:06:18 +0000 differ |
1014 | === added file 'cli/optionswidget.py' |
1015 | --- cli/optionswidget.py 1970-01-01 00:00:00 +0000 |
1016 | +++ cli/optionswidget.py 2010-03-02 06:06:17 +0000 |
1017 | @@ -0,0 +1,45 @@ |
1018 | +# Back In Time |
1019 | +# Copyright (C) 2010 Ryan Ahearn |
1020 | +# |
1021 | +# This program is free software; you can redistribute it and/or modify |
1022 | +# it under the terms of the GNU General Public License as published by |
1023 | +# the Free Software Foundation; either version 2 of the License, or |
1024 | +# (at your option) any later version. |
1025 | +# |
1026 | +# This program is distributed in the hope that it will be useful, |
1027 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1028 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1029 | +# GNU General Public License for more details. |
1030 | +# |
1031 | +# You should have received a copy of the GNU General Public License along |
1032 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1033 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1034 | + |
1035 | +import urwid |
1036 | +import gettext |
1037 | + |
1038 | +import logger |
1039 | + |
1040 | +_=gettext.gettext |
1041 | + |
1042 | +class OptionsWidget(urwid.WidgetWrap): |
1043 | + |
1044 | + def __init__( self, config ): |
1045 | + self._config = config |
1046 | + |
1047 | + pile_list = [ |
1048 | + urwid.CheckBox( _('Enable notifications'), config.is_notify_enabled(), on_state_change=self.flip_notify ), |
1049 | + urwid.CheckBox( _('Disable snapshots when on battery'), config.is_no_on_battery_enabled(), on_state_change=self.flip_battery ), |
1050 | + urwid.CheckBox( _('Backup files on restore'), config.is_backup_on_restore_enabled(), on_state_change=self.flip_backup_on_restore ) |
1051 | + ] |
1052 | + display_widget = urwid.Pile( pile_list ) |
1053 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1054 | + |
1055 | + def flip_notify( self, check_box, new_state ): |
1056 | + self._config.set_notify_enabled( new_state ) |
1057 | + |
1058 | + def flip_battery( self, check_box, new_state ): |
1059 | + self._config.set_no_on_battery_enabled( new_state ) |
1060 | + |
1061 | + def flip_backup_on_restore( self, check_box, new_state ): |
1062 | + self._config.set_backup_on_restore( new_state ) |
1063 | |
1064 | === added file 'cli/profilewidget.py' |
1065 | --- cli/profilewidget.py 1970-01-01 00:00:00 +0000 |
1066 | +++ cli/profilewidget.py 2010-03-02 06:06:17 +0000 |
1067 | @@ -0,0 +1,162 @@ |
1068 | +# Back In Time |
1069 | +# Copyright (C) 2010 Ryan Ahearn |
1070 | +# |
1071 | +# This program is free software; you can redistribute it and/or modify |
1072 | +# it under the terms of the GNU General Public License as published by |
1073 | +# the Free Software Foundation; either version 2 of the License, or |
1074 | +# (at your option) any later version. |
1075 | +# |
1076 | +# This program is distributed in the hope that it will be useful, |
1077 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1078 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1079 | +# GNU General Public License for more details. |
1080 | +# |
1081 | +# You should have received a copy of the GNU General Public License along |
1082 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1083 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1084 | + |
1085 | +import urwid |
1086 | +import gettext |
1087 | + |
1088 | +import logger |
1089 | + |
1090 | +_=gettext.gettext |
1091 | + |
1092 | +class ProfileWidget(urwid.WidgetWrap): |
1093 | + |
1094 | + def __init__( self, main_win, config, display_buttons=True ): |
1095 | + self._main_win = main_win |
1096 | + self._config = config |
1097 | + |
1098 | + current_profile = config.get_current_profile() |
1099 | + profile_ids = config.get_profiles() |
1100 | + profiles = [] |
1101 | + for profile_id in profile_ids: |
1102 | + profile_name = config.get_profile_name( profile_id ) |
1103 | + if profile_id == current_profile: |
1104 | + urwid.RadioButton( profiles, profile_name, True, self.profile_changed, profile_id ) |
1105 | + else: |
1106 | + urwid.RadioButton( profiles, profile_name, False, self.profile_changed, profile_id ) |
1107 | + chooser = urwid.Pile( profiles ) |
1108 | + |
1109 | + pile_list = [ |
1110 | + urwid.Text( _('Choose a profile') ), |
1111 | + urwid.Divider(), |
1112 | + chooser, |
1113 | + urwid.Divider() |
1114 | + ] |
1115 | + |
1116 | + if display_buttons: |
1117 | + buttons = [ |
1118 | + urwid.Button( _('Edit'), self.edit_profile ), |
1119 | + urwid.Button( _('New'), self.add_profile ) |
1120 | + ] |
1121 | + if len( profile_ids ) > 1: |
1122 | + buttons.append( urwid.Button( _('Delete'), self.delete_profile ) ) |
1123 | + pile_list.append( urwid.GridFlow( [ urwid.AttrWrap( button, 'button', 'button_focus' ) for button in buttons ], 10, 2, 1, 'center' ) ) |
1124 | + |
1125 | + display_widget = urwid.Pile( pile_list ) |
1126 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1127 | + |
1128 | + def profile_changed( self, button, new_state, user_data ): |
1129 | + if new_state: |
1130 | + self._config.set_current_profile( user_data ) |
1131 | + self._main_win.update_profile_name() |
1132 | + |
1133 | + def add_profile( self, button ): |
1134 | + self._main_win.update_content( AddProfileWidget( self._main_win, self._config ), 5 ) |
1135 | + |
1136 | + def edit_profile( self, button ): |
1137 | + self._main_win.update_content( EditProfileWidget( self._main_win, self._config ), 5 ) |
1138 | + |
1139 | + def delete_profile( self, button ): |
1140 | + self._main_win.update_content( DeleteProfileWidget( self._main_win, self._config ), 5 ) |
1141 | + |
1142 | + def go_to_profile_list( self, button=None ): |
1143 | + self._main_win.update_profile_name() |
1144 | + self._main_win.update_content( ProfileWidget( self._main_win, self._config ), 5 ) |
1145 | + |
1146 | + |
1147 | +class EditProfileWidget(ProfileWidget): |
1148 | + |
1149 | + def __init__( self, main_win, config ): |
1150 | + self._main_win = main_win |
1151 | + self._config = config |
1152 | + |
1153 | + self._edit_box = urwid.Edit(( 'body', _('Enter new name for profile') + ' ' + config.get_profile_name() + ': ' )) |
1154 | + self._error = urwid.Text( '' ) |
1155 | + pile_list = [ |
1156 | + urwid.AttrWrap( self._edit_box, 'edit_box', 'edit_focus' ), |
1157 | + urwid.AttrWrap( self._error, 'error' ), |
1158 | + urwid.Divider(), |
1159 | + urwid.GridFlow( [ |
1160 | + urwid.AttrWrap( urwid.Button( _('OK'), self.ok_pressed ), 'button', 'button_focus' ), |
1161 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.go_to_profile_list ), 'button', 'button_focus' ) |
1162 | + ], 10, 2, 1, 'right' ) |
1163 | + ] |
1164 | + |
1165 | + display_widget = urwid.Pile( pile_list ) |
1166 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1167 | + |
1168 | + def ok_pressed( self, button ): |
1169 | + name = self._edit_box.get_edit_text().strip() |
1170 | + if name == '': |
1171 | + self._error.set_text( _('Profile must be given a name') ) |
1172 | + elif self._config.set_profile_name( name ): |
1173 | + self.go_to_profile_list() |
1174 | + else: |
1175 | + self._error.set_text( _('Profile name already exists, choose another') ) |
1176 | + |
1177 | + |
1178 | +class AddProfileWidget(ProfileWidget): |
1179 | + |
1180 | + def __init__( self, main_win, config ): |
1181 | + self._main_win = main_win |
1182 | + self._config = config |
1183 | + |
1184 | + self._edit_box = urwid.Edit(( 'body', _('Enter name for new profile') + ': ' )) |
1185 | + self._error = urwid.Text( '' ) |
1186 | + pile_list = [ |
1187 | + urwid.AttrWrap( self._edit_box, 'edit_box', 'edit_focus' ), |
1188 | + urwid.AttrWrap( self._error, 'error' ), |
1189 | + urwid.Divider(), |
1190 | + urwid.GridFlow([ |
1191 | + urwid.AttrWrap( urwid.Button( _('OK'), self.ok_pressed ), 'button', 'button_focus' ), |
1192 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.go_to_profile_list ), 'button', 'button_focus' ) |
1193 | + ], 10, 2, 1, 'right' ) |
1194 | + ] |
1195 | + |
1196 | + display_widget = urwid.Pile( pile_list ) |
1197 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1198 | + |
1199 | + def ok_pressed( self, button ): |
1200 | + name = self._edit_box.get_edit_text().strip() |
1201 | + if name == '': |
1202 | + self._error.set_text( _('Profile must be given a name') ) |
1203 | + elif self._config.add_profile( name ): |
1204 | + self.go_to_profile_list() |
1205 | + else: |
1206 | + self._error.set_text( _('Profile name already exists, choose another') ) |
1207 | + |
1208 | + |
1209 | +class DeleteProfileWidget(ProfileWidget): |
1210 | + |
1211 | + def __init__( self, main_win, config ): |
1212 | + self._main_win = main_win |
1213 | + self._config = config |
1214 | + |
1215 | + pile_list = [ |
1216 | + urwid.Text( _('Are You Sure you want to delete profile') + ' "' + config.get_profile_name() + '"' ), |
1217 | + urwid.Divider(), |
1218 | + urwid.GridFlow([ |
1219 | + urwid.AttrWrap( urwid.Button( _('Yes'), self.yes_pressed ), 'button', 'button_focus' ), |
1220 | + urwid.AttrWrap( urwid.Button( _('No'), self.go_to_profile_list ), 'button', 'button_focus' ) |
1221 | + ], 10, 2, 1, 'right' ) |
1222 | + ] |
1223 | + |
1224 | + display_widget = urwid.Pile( pile_list ) |
1225 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1226 | + |
1227 | + def yes_pressed( self, button ): |
1228 | + self._config.remove_profile() |
1229 | + self.go_to_profile_list() |
1230 | |
1231 | === added file 'cli/removesnapshot.py' |
1232 | --- cli/removesnapshot.py 1970-01-01 00:00:00 +0000 |
1233 | +++ cli/removesnapshot.py 2010-03-02 06:06:17 +0000 |
1234 | @@ -0,0 +1,51 @@ |
1235 | +# Back In Time |
1236 | +# Copyright (C) 2010 Ryan Ahearn |
1237 | +# |
1238 | +# This program is free software; you can redistribute it and/or modify |
1239 | +# it under the terms of the GNU General Public License as published by |
1240 | +# the Free Software Foundation; either version 2 of the License, or |
1241 | +# (at your option) any later version. |
1242 | +# |
1243 | +# This program is distributed in the hope that it will be useful, |
1244 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1245 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1246 | +# GNU General Public License for more details. |
1247 | +# |
1248 | +# You should have received a copy of the GNU General Public License along |
1249 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1250 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1251 | + |
1252 | +import urwid |
1253 | +import gettext |
1254 | + |
1255 | +import logger |
1256 | +import restorewidget |
1257 | +import snapshots |
1258 | + |
1259 | +_=gettext.gettext |
1260 | + |
1261 | +class RemoveSnapshot(urwid.WidgetWrap): |
1262 | + |
1263 | + def __init__( self, main_win, config ): |
1264 | + self._main_win = main_win |
1265 | + self._config = config |
1266 | + self._snapshots = snapshots.Snapshots( config ) |
1267 | + |
1268 | + pile_list = [ |
1269 | + urwid.Text( _('Are you sure you want to remove snapshot') + ' "' + main_win.selected_snapshot_name + '"' ), |
1270 | + urwid.Divider(), |
1271 | + urwid.GridFlow( [ |
1272 | + urwid.AttrWrap( urwid.Button( _('Yes'), self.yes_pressed ), 'button', 'button_focus' ), |
1273 | + urwid.AttrWrap( urwid.Button( _('No'), self.go_home ), 'button', 'button_focus' ) |
1274 | + ], 10, 2, 1, 'right' ) |
1275 | + ] |
1276 | + |
1277 | + display_widget = urwid.Pile( pile_list ) |
1278 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1279 | + |
1280 | + def yes_pressed( self, button ): |
1281 | + self._snapshots.remove_snapshot( self._main_win.selected_snapshot ) |
1282 | + self.go_home() |
1283 | + |
1284 | + def go_home( self, button=None ): |
1285 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
1286 | |
1287 | === added file 'cli/removewidget.py' |
1288 | --- cli/removewidget.py 1970-01-01 00:00:00 +0000 |
1289 | +++ cli/removewidget.py 2010-03-02 06:06:17 +0000 |
1290 | @@ -0,0 +1,114 @@ |
1291 | +# Back In Time |
1292 | +# Copyright (C) 2010 Ryan Ahearn |
1293 | +# |
1294 | +# This program is free software; you can redistribute it and/or modify |
1295 | +# it under the terms of the GNU General Public License as published by |
1296 | +# the Free Software Foundation; either version 2 of the License, or |
1297 | +# (at your option) any later version. |
1298 | +# |
1299 | +# This program is distributed in the hope that it will be useful, |
1300 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1301 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1302 | +# GNU General Public License for more details. |
1303 | +# |
1304 | +# You should have received a copy of the GNU General Public License along |
1305 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1306 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1307 | + |
1308 | +import urwid |
1309 | +import gettext |
1310 | + |
1311 | +import logger |
1312 | + |
1313 | +_=gettext.gettext |
1314 | + |
1315 | +class RemoveWidget(urwid.WidgetWrap): |
1316 | + |
1317 | + def __init__( self, config ): |
1318 | + self._config = config |
1319 | + |
1320 | + old_enabled, self._remove_old_value, self._remove_old_unit = config.get_remove_old_snapshots() |
1321 | + self._remove_old_enabled = urwid.CheckBox( _('Older than:'), old_enabled, on_state_change=self.flip_old_enabled ) |
1322 | + remove_old_value_box = urwid.IntEdit( '', self._remove_old_value ) |
1323 | + urwid.connect_signal( remove_old_value_box, 'change', self.remove_old_value_changed ) |
1324 | + remove_units = [] |
1325 | + for key, value in sorted( config.REMOVE_OLD_BACKUP_UNITS.items() ): |
1326 | + if self._remove_old_unit == key: |
1327 | + urwid.RadioButton( remove_units, value, True, self.remove_old_unit_changed, key ) |
1328 | + else: |
1329 | + urwid.RadioButton( remove_units, value, False, self.remove_old_unit_changed, key ) |
1330 | + remove_unit_chooser = urwid.Pile( remove_units ) |
1331 | + age_columns = urwid.Columns( [ |
1332 | + self._remove_old_enabled, |
1333 | + urwid.AttrWrap( remove_old_value_box, 'edit_box', 'edit_focus' ), |
1334 | + remove_unit_chooser |
1335 | + ], 1 ) |
1336 | + |
1337 | + space_enabled, self._free_space_value, self._free_space_unit = config.get_min_free_space() |
1338 | + self._free_space_enabled = urwid.CheckBox( _('If free space is less than:'), space_enabled, on_state_change=self.flip_free_space_enabled ) |
1339 | + free_space_value_box = urwid.IntEdit( '', self._free_space_value ) |
1340 | + urwid.connect_signal( free_space_value_box, 'change', self.free_space_value_changed ) |
1341 | + free_space_units = [] |
1342 | + for key, value in sorted( config.MIN_FREE_SPACE_UNITS.items() ): |
1343 | + if self._free_space_unit == key: |
1344 | + urwid.RadioButton( free_space_units, value, True, self.free_space_unit_changed, key ) |
1345 | + else: |
1346 | + urwid.RadioButton( free_space_units, value, False, self.free_space_unit_changed, key ) |
1347 | + space_unit_chooser = urwid.Pile( free_space_units ) |
1348 | + space_columns = urwid.Columns( [ |
1349 | + self._free_space_enabled, |
1350 | + urwid.AttrWrap( free_space_value_box, 'edit_box', 'edit_focus' ), |
1351 | + space_unit_chooser |
1352 | + ], 1 ) |
1353 | + |
1354 | + pile_list = [ |
1355 | + age_columns, |
1356 | + urwid.Divider(), |
1357 | + space_columns, |
1358 | + urwid.Divider(), |
1359 | + urwid.CheckBox( _('Smart remove'), config.get_smart_remove(), on_state_change=self.flip_smart_remove ), |
1360 | + urwid.Padding( urwid.Text( _('- keep all snapshots from today and yesterday') ), left=4 ), |
1361 | + urwid.Padding( urwid.Text( _('- keep one snapshot for the last week and one for two weeks ago') ), left=4 ), |
1362 | + urwid.Padding( urwid.Text( _('- keep one snapshot per month for all previous months of this year and all months of the last year') ), left=4 ), |
1363 | + urwid.Padding( urwid.Text( _('- keep one snapshot per year for all other years') ), left=4 ), |
1364 | + urwid.Divider(), |
1365 | + urwid.CheckBox( _("Don't remove named snapshots"), config.get_dont_remove_named_snapshots(), on_state_change=self.flip_remove_named ) |
1366 | + ] |
1367 | + display_widget = urwid.Pile( pile_list ) |
1368 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1369 | + |
1370 | + def flip_remove_named( self, check_box, new_state ): |
1371 | + self._config.set_dont_remove_named_snapshots( new_state ) |
1372 | + |
1373 | + def flip_smart_remove( self, check_box, new_state ): |
1374 | + self._config.set_smart_remove( new_state ) |
1375 | + |
1376 | + def flip_free_space_enabled( self, check_box, new_state ): |
1377 | + self._config.set_min_free_space( new_state, self._free_space_value, self._free_space_unit ) |
1378 | + |
1379 | + def free_space_value_changed( self, edit, new_edit_text ): |
1380 | + if new_edit_text == '': |
1381 | + self._free_space_value = 0 |
1382 | + else: |
1383 | + self._free_space_value = new_edit_text.strip() |
1384 | + self._config.set_min_free_space( self._free_space_enabled.get_state(), self._free_space_value, self._free_space_unit ) |
1385 | + |
1386 | + def free_space_unit_changed( self, check_box, new_state, user_data ): |
1387 | + if new_state: |
1388 | + self._free_space_unit = user_data |
1389 | + self._config.set_min_free_space( self._free_space_enabled.get_state(), self._free_space_value, self._free_space_unit ) |
1390 | + |
1391 | + def flip_old_enabled( self, check_box, new_state ): |
1392 | + self._config.set_remove_old_snapshots( new_state, self._remove_old_value, self._remove_old_unit ) |
1393 | + |
1394 | + def remove_old_value_changed( self, edit, new_edit_text ): |
1395 | + if new_edit_text == '': |
1396 | + self._remove_old_value = 0 |
1397 | + else: |
1398 | + self._remove_old_value = new_edit_text.strip() |
1399 | + self._config.set_remove_old_snapshots( self._remove_old_enabled.get_state(), self._remove_old_value, self._remove_old_unit ) |
1400 | + |
1401 | + def remove_old_unit_changed( self, check_box, new_state, user_data ): |
1402 | + if new_state: |
1403 | + self._remove_old_unit = user_data |
1404 | + self._config.set_remove_old_snapshots( self._remove_old_enabled.get_state(), self._remove_old_value, self._remove_old_unit ) |
1405 | |
1406 | === added file 'cli/restorewidget.py' |
1407 | --- cli/restorewidget.py 1970-01-01 00:00:00 +0000 |
1408 | +++ cli/restorewidget.py 2010-03-02 06:06:17 +0000 |
1409 | @@ -0,0 +1,107 @@ |
1410 | +# Back In Time |
1411 | +# Copyright (C) 2010 Ryan Ahearn |
1412 | +# |
1413 | +# This program is free software; you can redistribute it and/or modify |
1414 | +# it under the terms of the GNU General Public License as published by |
1415 | +# the Free Software Foundation; either version 2 of the License, or |
1416 | +# (at your option) any later version. |
1417 | +# |
1418 | +# This program is distributed in the hope that it will be useful, |
1419 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1420 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1421 | +# GNU General Public License for more details. |
1422 | +# |
1423 | +# You should have received a copy of the GNU General Public License along |
1424 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1425 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1426 | + |
1427 | + |
1428 | +import urwid |
1429 | +import datetime |
1430 | +import gettext |
1431 | + |
1432 | +import logger |
1433 | +import snapshots |
1434 | +import viewerwidget |
1435 | + |
1436 | +_=gettext.gettext |
1437 | + |
1438 | +class RestoreWidget(urwid.WidgetWrap): |
1439 | + |
1440 | + def __init__( self, main_win, config ): |
1441 | + self._main_win = main_win |
1442 | + self._config = config |
1443 | + |
1444 | + self._snapshots = snapshots.Snapshots( config ) |
1445 | + snapshots_pile = [ |
1446 | + urwid.Text( _('Snapshots') ), |
1447 | + urwid.Divider(), |
1448 | + ] |
1449 | + snapshots_pile.extend( self.build_snapshots_pile() ) |
1450 | + |
1451 | + display_widget = urwid.Columns( [ |
1452 | + urwid.Pile( snapshots_pile ), |
1453 | + ( 'weight', 3, viewerwidget.ViewerWidget( main_win, config, self._snapshots ) ) |
1454 | + ], 1 ) |
1455 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1456 | + |
1457 | + def build_snapshots_pile( self ): |
1458 | + snapshots_list = self._snapshots.get_snapshots_list() |
1459 | + groups = [] |
1460 | + now = datetime.date.today() |
1461 | + |
1462 | + #today |
1463 | + date = now |
1464 | + groups.append( ( _('Today'), self._snapshots.get_snapshot_id( date ), [] ) ) |
1465 | + #yesterday |
1466 | + date = now - datetime.timedelta( days = 1 ) |
1467 | + groups.append( ( _('Yesterday'), self._snapshots.get_snapshot_id( date ), [] ) ) |
1468 | + #this week |
1469 | + date = now - datetime.timedelta( days = now.weekday() ) |
1470 | + groups.append( ( _('This week'), self._snapshots.get_snapshot_id( date ), [] ) ) |
1471 | + #last week |
1472 | + date = now - datetime.timedelta( days = now.weekday() + 7 ) |
1473 | + groups.append( ( _('Last week'), self._snapshots.get_snapshot_id( date ), [] ) ) |
1474 | + #any other groups |
1475 | + for snapshot_id in snapshots_list: |
1476 | + found = False |
1477 | + for group in groups: |
1478 | + if snapshot_id >= group[1]: |
1479 | + group[2].append( snapshot_id ) |
1480 | + found = True |
1481 | + break |
1482 | + |
1483 | + if not found: |
1484 | + year = int( snapshot_id[0:4] ) |
1485 | + month = int( snapshot_id[4:6] ) |
1486 | + date = datetime.date( year, month, 1 ) |
1487 | + |
1488 | + group_name = '' |
1489 | + if year == now.year: |
1490 | + group_name = date.strftime( '%B' ).capitalize() |
1491 | + else: |
1492 | + group_name = date.strftime( '%B, %Y' ).capitalize() |
1493 | + |
1494 | + groups.append( ( group_name, self._snapshots.get_snapshot_id( date ), [ snapshot_id ] ) ) |
1495 | + |
1496 | + snapshots_buttons = [] |
1497 | + pile_list = [ |
1498 | + urwid.RadioButton( snapshots_buttons, _('Now'), self._main_win.is_selected_snapshot( '' ), self.change_snapshot, '' ) |
1499 | + ] |
1500 | + for group in groups: |
1501 | + if len( group[2] ) > 0: |
1502 | + pile_list.append( urwid.Text( group[0] ) ) |
1503 | + for snapshot_id in group[2]: |
1504 | + display_name = self._snapshots.get_snapshot_display_id( snapshot_id ) |
1505 | + user_name = self._snapshots.get_snapshot_name( snapshot_id ) |
1506 | + if len( user_name ) > 0: |
1507 | + display_name += ' - ' + user_name |
1508 | + pile_list.append( urwid.RadioButton( snapshots_buttons, display_name, self._main_win.is_selected_snapshot( snapshot_id ), self.change_snapshot, snapshot_id ) ) |
1509 | + |
1510 | + return pile_list |
1511 | + |
1512 | + def change_snapshot( self, check_box, new_state, user_data ): |
1513 | + if new_state: |
1514 | + self._main_win.selected_snapshot = user_data |
1515 | + self._main_win.selected_snapshot_name = check_box.get_label() |
1516 | + self._main_win.update_content( RestoreWidget( self._main_win, self._config ), 5 ) |
1517 | |
1518 | === added file 'cli/snapshotname.py' |
1519 | --- cli/snapshotname.py 1970-01-01 00:00:00 +0000 |
1520 | +++ cli/snapshotname.py 2010-03-02 06:06:17 +0000 |
1521 | @@ -0,0 +1,52 @@ |
1522 | +# Back In Time |
1523 | +# Copyright (C) 2010 Ryan Ahearn |
1524 | +# |
1525 | +# This program is free software; you can redistribute it and/or modify |
1526 | +# it under the terms of the GNU General Public License as published by |
1527 | +# the Free Software Foundation; either version 2 of the License, or |
1528 | +# (at your option) any later version. |
1529 | +# |
1530 | +# This program is distributed in the hope that it will be useful, |
1531 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1532 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1533 | +# GNU General Public License for more details. |
1534 | +# |
1535 | +# You should have received a copy of the GNU General Public License along |
1536 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1537 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1538 | + |
1539 | +import urwid |
1540 | +import gettext |
1541 | + |
1542 | +import logger |
1543 | +import restorewidget |
1544 | +import snapshots |
1545 | + |
1546 | +_=gettext.gettext |
1547 | + |
1548 | +class SnapshotName(urwid.WidgetWrap): |
1549 | + |
1550 | + def __init__( self, main_win, config ): |
1551 | + self._main_win = main_win |
1552 | + self._config = config |
1553 | + self._snapshots = snapshots.Snapshots( config ) |
1554 | + |
1555 | + self._edit_box = urwid.Edit(( 'body', _('Snapshot Name') + ': ' ), self._snapshots.get_snapshot_name( main_win.selected_snapshot ) ) |
1556 | + pile_list = [ |
1557 | + urwid.AttrWrap( self._edit_box, 'edit_box', 'edit_focus' ), |
1558 | + urwid.Divider(), |
1559 | + urwid.GridFlow( [ |
1560 | + urwid.AttrWrap( urwid.Button( _('OK'), self.ok_pressed ), 'button', 'button_focus' ), |
1561 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.cancel_pressed ), 'button', 'button_focus' ) |
1562 | + ], 10, 2, 1, 'right' ) |
1563 | + ] |
1564 | + |
1565 | + display_widget = urwid.Pile( pile_list ) |
1566 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1567 | + |
1568 | + def ok_pressed( self, button ): |
1569 | + self._snapshots.set_snapshot_name( self._main_win.selected_snapshot, self._edit_box.get_edit_text().strip() ) |
1570 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
1571 | + |
1572 | + def cancel_pressed( self, button ): |
1573 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
1574 | |
1575 | === added file 'cli/snapshotswidget.py' |
1576 | --- cli/snapshotswidget.py 1970-01-01 00:00:00 +0000 |
1577 | +++ cli/snapshotswidget.py 2010-03-02 06:06:17 +0000 |
1578 | @@ -0,0 +1,158 @@ |
1579 | +# Back In Time |
1580 | +# Copyright (C) 2010 Ryan Ahearn |
1581 | +# |
1582 | +# This program is free software; you can redistribute it and/or modify |
1583 | +# it under the terms of the GNU General Public License as published by |
1584 | +# the Free Software Foundation; either version 2 of the License, or |
1585 | +# (at your option) any later version. |
1586 | +# |
1587 | +# This program is distributed in the hope that it will be useful, |
1588 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1589 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1590 | +# GNU General Public License for more details. |
1591 | +# |
1592 | +# You should have received a copy of the GNU General Public License along |
1593 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1594 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1595 | + |
1596 | + |
1597 | +import os.path |
1598 | +import subprocess |
1599 | +import tempfile |
1600 | +import urwid |
1601 | +import gettext |
1602 | + |
1603 | +import logger |
1604 | +import restorewidget |
1605 | + |
1606 | +_=gettext.gettext |
1607 | + |
1608 | +class SnapshotsWidget(urwid.WidgetWrap): |
1609 | + |
1610 | + def __init__( self, main_win, config, snapshots, path ): |
1611 | + self._main_win = main_win |
1612 | + self._config = config |
1613 | + self._snapshots = snapshots |
1614 | + self._path = path |
1615 | + self._selected_left = '' |
1616 | + self._selected_right = None |
1617 | + |
1618 | + left_side, right_side = self._build_snapshot_lists() |
1619 | + pile_list = [ |
1620 | + urwid.Text( _('Diff versions of') + ': %s' % path ), |
1621 | + urwid.Divider(), |
1622 | + urwid.Columns( [ |
1623 | + urwid.Pile( left_side ), |
1624 | + urwid.Pile( right_side ) |
1625 | + ], 1 ), |
1626 | + urwid.Divider(), |
1627 | + urwid.GridFlow( [ |
1628 | + urwid.AttrWrap( urwid.Button( _('Jump to'), self.jump ), 'button', 'button_focus' ), |
1629 | + urwid.AttrWrap( urwid.Button( _('Diff'), self.diff ), 'button', 'button_focus' ), |
1630 | + urwid.AttrWrap( urwid.Button( _('Cancel'), self.go_back ), 'button', 'button_focus' ) |
1631 | + ], 11, 2, 1, 'right' ) |
1632 | + ] |
1633 | + |
1634 | + display_widget = urwid.Pile( pile_list ) |
1635 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1636 | + |
1637 | + def _build_snapshot_lists( self ): |
1638 | + snapshots_list = self._snapshots.get_snapshots_list() |
1639 | + left_list = [ |
1640 | + urwid.Text( _('Snapshots') + ':' ), |
1641 | + urwid.Divider() |
1642 | + ] |
1643 | + left_list_buttons = [] |
1644 | + right_list = [ |
1645 | + urwid.Text( _('Diff with') + ':' ), |
1646 | + urwid.Divider() |
1647 | + ] |
1648 | + right_list_buttons = [] |
1649 | + |
1650 | + path = self._snapshots.get_snapshot_path_to( self._main_win.selected_snapshot, self._path ) |
1651 | + isdir = os.path.isdir( path ) |
1652 | + |
1653 | + # add now |
1654 | + path = self._path |
1655 | + if os.path.lexists( path ): |
1656 | + if os.path.isdir( path ) == isdir: |
1657 | + left_list.append( urwid.RadioButton( left_list_buttons, _('Now'), True, self.left_changed, '' ) ) |
1658 | + right_list.append( urwid.RadioButton( right_list_buttons, _('Now'), False, self.right_changed, '' ) ) |
1659 | + |
1660 | + # add snapshots |
1661 | + for snapshot in snapshots_list: |
1662 | + path = self._snapshots.get_snapshot_path_to( snapshot, self._path ) |
1663 | + if os.path.lexists( path ): |
1664 | + if os.path.isdir( path ) == isdir: |
1665 | + display_name = self._snapshots.get_snapshot_display_id( snapshot ) |
1666 | + user_name = self._snapshots.get_snapshot_name( snapshot ) |
1667 | + if len( user_name ) > 0: |
1668 | + display_name += ' - ' + user_name |
1669 | + if self._main_win.is_selected_snapshot( snapshot ): |
1670 | + selected = True |
1671 | + self._selected_right = snapshot |
1672 | + else: |
1673 | + selected = False |
1674 | + left_list.append( urwid.RadioButton( left_list_buttons, display_name, False, self.left_changed, snapshot ) ) |
1675 | + right_list.append( urwid.RadioButton( right_list_buttons, display_name, selected, self.right_changed, snapshot ) ) |
1676 | + |
1677 | + return left_list, right_list |
1678 | + |
1679 | + def left_changed( self, radio_button, new_state, user_data ): |
1680 | + if new_state: |
1681 | + self._selected_left = user_data |
1682 | + |
1683 | + def right_changed( self, radio_button, new_state, user_data ): |
1684 | + if new_state: |
1685 | + self._selected_right = user_data |
1686 | + |
1687 | + def jump( self, button ): |
1688 | + self._main_win.selected_snapshot = self._selected_left |
1689 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
1690 | + |
1691 | + def diff( self, button ): |
1692 | + if self._selected_right is not None: |
1693 | + self._main_win.update_content( DiffWidget( self._main_win, self._config, self._snapshots, self._path, self._selected_left, self._selected_right ), 5 ) |
1694 | + |
1695 | + def go_back( self, button ): |
1696 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
1697 | + |
1698 | +class DiffWidget(SnapshotsWidget): |
1699 | + def __init__( self, main_win, config, snapshots, path, selected_left, selected_right ): |
1700 | + self._main_win = main_win |
1701 | + self._config = config |
1702 | + |
1703 | + path_left = snapshots.get_snapshot_path_to( selected_left, path ) |
1704 | + path_right = snapshots.get_snapshot_path_to( selected_right, path ) |
1705 | + |
1706 | + diff_cmd = 'diff "%s" "%s"' % ( path_left, path_right ) |
1707 | + logger.info( 'diff cmd = "%s"' % diff_cmd ) |
1708 | + |
1709 | + wc_cmd = '%s | wc -l' % diff_cmd |
1710 | + callback = subprocess.Popen( wc_cmd, shell=True, stdout=subprocess.PIPE ) |
1711 | + output = callback.communicate() |
1712 | + if main_win.main_loop.screen_size: |
1713 | + rows = main_win.main_loop.screen_size[1] |
1714 | + else: |
1715 | + rows = main_win.main_loop.screen.get_cols_rows()[1] |
1716 | + |
1717 | + if int( output[0] ) > rows: |
1718 | + temp_file, temp_file_name = tempfile.mkstemp( '_bitdiff', os.path.basename( path ), text=True ) |
1719 | + output_text = _('This diff was too long for the window, it has been written to') + ': %s' % temp_file_name |
1720 | + callback = subprocess.Popen( diff_cmd, shell=True, stdout=temp_file ) |
1721 | + callback.communicate() |
1722 | + else: |
1723 | + callback = subprocess.Popen( diff_cmd, shell=True, stdout=subprocess.PIPE ) |
1724 | + output = callback.communicate() |
1725 | + output_text = output[0] |
1726 | + |
1727 | + pile_list = [ |
1728 | + urwid.Text( diff_cmd ), |
1729 | + urwid.Divider(), |
1730 | + urwid.Text( output_text ), |
1731 | + urwid.Divider(), |
1732 | + urwid.AttrWrap( urwid.Button( _('OK'), self.go_back ), 'button', 'button_focus' ) |
1733 | + ] |
1734 | + |
1735 | + display_widget = urwid.Pile( pile_list ) |
1736 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1737 | |
1738 | === added file 'cli/viewerwidget.py' |
1739 | --- cli/viewerwidget.py 1970-01-01 00:00:00 +0000 |
1740 | +++ cli/viewerwidget.py 2010-03-02 06:06:17 +0000 |
1741 | @@ -0,0 +1,132 @@ |
1742 | +# Back In Time |
1743 | +# Copyright (C) 2010 Ryan Ahearn |
1744 | +# |
1745 | +# This program is free software; you can redistribute it and/or modify |
1746 | +# it under the terms of the GNU General Public License as published by |
1747 | +# the Free Software Foundation; either version 2 of the License, or |
1748 | +# (at your option) any later version. |
1749 | +# |
1750 | +# This program is distributed in the hope that it will be useful, |
1751 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1752 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1753 | +# GNU General Public License for more details. |
1754 | +# |
1755 | +# You should have received a copy of the GNU General Public License along |
1756 | +# with this program; if not, write to the Free Software Foundation, Inc., |
1757 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
1758 | + |
1759 | + |
1760 | +import os |
1761 | +import os.path |
1762 | +import urwid |
1763 | +import gettext |
1764 | + |
1765 | +import logger |
1766 | +import restorewidget |
1767 | +import copywidget |
1768 | +import snapshotswidget |
1769 | + |
1770 | +_=gettext.gettext |
1771 | + |
1772 | +class ViewerWidget(urwid.WidgetWrap): |
1773 | + |
1774 | + def __init__( self, main_win, config, snapshots ): |
1775 | + self._main_win = main_win |
1776 | + self._config = config |
1777 | + self._snapshots = snapshots |
1778 | + self._selected = '' |
1779 | + |
1780 | + if main_win.show_hidden: |
1781 | + hidden_label = _('Hide hidden files') |
1782 | + else: |
1783 | + hidden_label = _('Show hidden files') |
1784 | + self.build_fileview() |
1785 | + pile_list = [ |
1786 | + urwid.Columns( [ |
1787 | + ( 'fixed', 6, urwid.AttrWrap( urwid.Button( _('Up'), self.up_directory ), 'button', 'button_focus' ) ), |
1788 | + urwid.Text( main_win.current_directory, wrap='clip' ) |
1789 | + ], 1), |
1790 | + urwid.Divider(), |
1791 | + urwid.Columns( [ |
1792 | + ( 'fixed', 21, urwid.AttrWrap( urwid.Button( hidden_label, self.flip_hidden ), 'button', 'button_focus' ) ), |
1793 | + ( 'fixed', 11, urwid.AttrWrap( urwid.Button( _('Restore'), self.restore ), 'button', 'button_focus' ) ), |
1794 | + ( 'fixed', 8, urwid.AttrWrap( urwid.Button( _('Copy'), self.copy ), 'button', 'button_focus' ) ), |
1795 | + ( 'fixed', 13,urwid.AttrWrap( urwid.Button( _('Snapshots'), self.snapshots ), 'button', 'button_focus' ) ) |
1796 | + ], 1 ), |
1797 | + urwid.Divider(), |
1798 | + urwid.Columns( [ self.build_shortcuts(), |
1799 | + ( 'weight', 3, urwid.Pile( self._file_list ) ) ], 1 ) |
1800 | + ] |
1801 | + display_widget = urwid.Pile( pile_list ) |
1802 | + urwid.WidgetWrap.__init__( self, display_widget ) |
1803 | + |
1804 | + def build_fileview( self ): |
1805 | + self._file_list = [ |
1806 | + urwid.Text( _('Files and Folders') ), |
1807 | + urwid.Divider() |
1808 | + ] |
1809 | + |
1810 | + sid = self._main_win.selected_snapshot |
1811 | + |
1812 | + full_path = self._snapshots.get_snapshot_path_to( sid, self._main_win.current_directory ) |
1813 | + |
1814 | + if not self._snapshots.can_open_path( sid, full_path ): |
1815 | + self._file_list.append( urwid.Text( _('This folder does not exist') ) ) |
1816 | + self._file_list.append( urwid.Text( _('in current snapshot !' ) ) ) |
1817 | + return |
1818 | + |
1819 | + directory = os.listdir( full_path ) |
1820 | + decorated = [ ( not os.path.isdir( os.path.join( full_path, file_name ) ), file_name ) for file_name in directory ] |
1821 | + decorated.sort() |
1822 | + restore_radios = [] |
1823 | + for is_file, file_name in decorated: |
1824 | + if self._main_win.show_hidden or not file_name.startswith( '.' ): |
1825 | + if is_file: |
1826 | + self._file_list.append( urwid.RadioButton( restore_radios, file_name, False, self.select_for_restore, file_name ) ) |
1827 | + else: |
1828 | + self._file_list.append( urwid.Columns( [ |
1829 | + ( 'fixed', 4, urwid.RadioButton( restore_radios, '', False, self.select_for_restore, file_name ) ), |
1830 | + urwid.AttrWrap( urwid.Button( file_name, self.go_to_directory ), 'button', 'button_focus' ) |
1831 | + ], 0 ) ) |
1832 | + |
1833 | + |
1834 | + def select_for_restore( self, radio_button, new_state, user_data ): |
1835 | + if new_state: |
1836 | + self._selected = os.path.join( self._main_win.current_directory, user_data ) |
1837 | + |
1838 | + def go_to_directory( self, button ): |
1839 | + new_directory = os.path.join( self._main_win.current_directory, button.get_label() ) |
1840 | + self._main_win.update_current_directory( new_directory ) |
1841 | + |
1842 | + def build_shortcuts( self ): |
1843 | + pile_list = [ urwid.Text( _('Shortcuts') ) ] |
1844 | + |
1845 | + included_folders = self._config.get_include_folders() |
1846 | + for label in included_folders: |
1847 | + pile_list.append( urwid.AttrWrap( urwid.Button( label, self.go_to_shortcut ), 'button', 'button_focus' ) ) |
1848 | + |
1849 | + return urwid.Pile( pile_list ) |
1850 | + |
1851 | + def go_to_shortcut( self, button ): |
1852 | + self._main_win.update_current_directory( button.get_label() ) |
1853 | + |
1854 | + def up_directory( self, button ): |
1855 | + self._main_win.update_current_directory( os.path.dirname( self._main_win.current_directory ) ) |
1856 | + |
1857 | + def flip_hidden( self, button ): |
1858 | + self._main_win.show_hidden = not self._main_win.show_hidden |
1859 | + self._main_win.update_content( restorewidget.RestoreWidget( self._main_win, self._config ), 5 ) |
1860 | + |
1861 | + def restore( self, button ): |
1862 | + if self._main_win.selected_snapshot != '' and self._selected != '': |
1863 | + self._snapshots.restore( self._main_win.selected_snapshot, self._selected ) |
1864 | + |
1865 | + def copy( self, button ): |
1866 | + if self._main_win.selected_snapshot != '' and self._selected != '': |
1867 | + source_path = self._snapshots.get_snapshot_path_to( self._main_win.selected_snapshot, self._selected ) |
1868 | + self._main_win.update_content( copywidget.CopyWidget( self._main_win, self._config, source_path ), 5 ) |
1869 | + |
1870 | + def snapshots( self, button ): |
1871 | + if self._selected != '': |
1872 | + self._main_win.update_content( snapshotswidget.SnapshotsWidget( self._main_win, self._config, self._snapshots, self._selected ), 5 ) |
1873 | + |
1874 | |
1875 | === modified file 'common/backintime.py' |
1876 | --- common/backintime.py 2009-12-17 10:18:53 +0000 |
1877 | +++ common/backintime.py 2010-03-02 06:06:18 +0000 |
1878 | @@ -83,7 +83,6 @@ |
1879 | |
1880 | def start_app( app_name = 'backintime', extra_args = [] ): |
1881 | cfg = config.Config() |
1882 | - print_version( cfg, app_name ) |
1883 | |
1884 | skip = False |
1885 | index = 0 |
1886 | @@ -111,6 +110,7 @@ |
1887 | sys.exit(0) |
1888 | |
1889 | if arg == '--version' or arg == '-v': |
1890 | + print_version( cfg, app_name ) |
1891 | sys.exit(0) |
1892 | |
1893 | if arg == '--license': |
1894 | |
1895 | === modified file 'common/logger.py' |
1896 | --- common/logger.py 2009-11-02 13:52:00 +0000 |
1897 | +++ common/logger.py 2010-03-02 06:06:18 +0000 |
1898 | @@ -27,14 +27,11 @@ |
1899 | syslog.closelog() |
1900 | |
1901 | def error( msg ): |
1902 | - print 'ERROR: ' + msg |
1903 | syslog.syslog( syslog.LOG_ERR, 'ERROR: ' + msg ) |
1904 | |
1905 | def warning( msg ): |
1906 | - print 'WARNING: ' + msg |
1907 | syslog.syslog( syslog.LOG_WARNING, 'WARNING: ' + msg ) |
1908 | |
1909 | def info( msg ): |
1910 | - print 'INFO: ' + msg |
1911 | syslog.syslog( syslog.LOG_INFO, 'INFO: ' + msg ) |
1912 | |
1913 | |
1914 | === modified file 'makedeb.sh' |
1915 | --- makedeb.sh 2009-05-12 10:13:25 +0000 |
1916 | +++ makedeb.sh 2010-03-02 06:06:17 +0000 |
1917 | @@ -1,6 +1,6 @@ |
1918 | #!/bin/bash |
1919 | |
1920 | -for i in common gnome kde4; do |
1921 | +for i in common gnome kde4 cli; do |
1922 | PKGNAME=`cat $i/debian_specific/control | grep "Package:" | cut -d" " -f2` |
1923 | PKGVER=`cat $i/debian_specific/control | grep "Version:" | cut -d" " -f2` |
1924 | PKGARCH=`cat $i/debian_specific/control | grep "Architecture:" | cut -d" " -f2` |
1925 | |
1926 | === modified file 'updateversion.sh' |
1927 | --- updateversion.sh 2009-04-27 13:43:00 +0000 |
1928 | +++ updateversion.sh 2010-03-02 06:06:17 +0000 |
1929 | @@ -12,6 +12,9 @@ |
1930 | echo "Update 'kde4/debian_specific/control'" |
1931 | sed -i -e "s/^Version: .*$/Version: $VERSION/" -e "s/backintime-common (= [^)]*)/backintime-common (= $VERSION)/" kde4/debian_specific/control |
1932 | |
1933 | +echo "Update 'cli/debian_specific/control'" |
1934 | +sed -i -e "s/^Version: .*$/Version: $VERSION/" -e "s/backintime-common (= [^)]*)/backintime-common (= $VERSION)/" cli/debian_specific/control |
1935 | + |
1936 | echo "Update 'common/config.py'" |
1937 | sed -i -e "s/^\tVERSION = '.*'$/\tVERSION = '$VERSION'/" common/config.py |
1938 | |
1939 | @@ -33,6 +36,16 @@ |
1940 | sed -i -e "s/\.TH\(.*\)\"version\([^\"]*\)\"\(.*\)$/.TH\1\"version $VERSION\"\3/" $FILE |
1941 | gzip --best $FILE |
1942 | |
1943 | +echo "Update CLI man page" |
1944 | +FILE=cli/man/C/backintime-config.1 |
1945 | +gzip -d $FILE.gz |
1946 | +sed -i -e "s/\.TH\(.*\)\"version\([^\"]*\)\"\(.*\)$/.TH\1\"version $VERSION\"\3/" $FILE |
1947 | +gzip --best $FILE |
1948 | +FILE=cli/man/C/backintime-restore.1 |
1949 | +gzip -d $FILE.gz |
1950 | +sed -i -e "s/\.TH\(.*\)\"version\([^\"]*\)\"\(.*\)$/.TH\1\"version $VERSION\"\3/" $FILE |
1951 | +gzip --best $FILE |
1952 | + |
1953 | echo "Update help .omf file" |
1954 | sed -i -e "s/^\([ \]*\)<version\([^0-9]*\)\([^\"]*\)\(.*\)$/\1<version\2$VERSION\4/" gnome/docbook/C/backintime-C.omf |
1955 |
Here's my first cut of a command line interface for back in time configuration and restore.
It's not the prettiest interface right now, but it seems functionally solid. All of the displayed strings have the gettext call around them, but I don't speak any other languages so I have left the language files alone.
I tried to leave common alone as much as possible, but I had to suppress a couple of print calls to clean up the display when a user kicked off taking a snapshot from inside of backintime-restore.
Let me know what you think.