1
from twisted.python import usage
3
from renamer import logging
4
from renamer.history import Action, Changeset
5
from renamer.plugin import Command, SubCommand
9
def getItem(store, storeID, acceptableTypes):
11
Get an Axiom Item from a store by ID and verify that it is an acceptable
15
storeID = int(storeID)
16
except (ValueError, TypeError):
17
raise usage.UsageError(
18
'Identifier %r is not an integer' % (storeID,))
20
item = store.getItemByID(storeID, default=None)
21
if not isinstance(item, acceptableTypes):
22
raise usage.UsageError(
23
'Invalid identifier %r' % (storeID,))
28
class _UndoMixin(object):
30
('ignore-errors', None, 'Do not stop the process when encountering OS errors')]
33
def undoActions(self, renamer, changeset, actions):
35
Undo specific actions from a changeset.
37
for action in actions:
38
msg = 'Simulating undo'
39
if not renamer.options['no-act']:
42
logging.msg('%s: %s' % (msg, action.asHumanly()), verbosity=3)
43
if not renamer.options['no-act']:
45
changeset.undo(action, renamer.options)
47
if not self['ignore-errors']:
49
logging.msg('Ignoring %r' % (e,), verbosity=3)
53
class UndoAction(SubCommand, _UndoMixin):
57
synopsis = '[options] <actionID>'
61
Undo a single action from a changeset. Consult "undo list" for action
66
def parseArgs(self, action):
67
self['action'] = action
70
def process(self, renamer):
71
action = getItem(renamer.store, self['action'], Action)
73
renamer, action.changeset, [action])
77
class UndoChangeset(SubCommand, _UndoMixin):
81
synopsis = '[options] <changesetID>'
85
Undo an entire changeset. Consult "undo list" for changeset identifiers.
89
def parseArgs(self, changeset):
90
self['changeset'] = changeset
93
def process(self, renamer):
94
changeset = getItem(renamer.store, self['changeset'], Changeset)
95
logging.msg('Undoing: %s' % (changeset.asHumanly(),),
97
actions = list(changeset.getActions())
99
renamer, changeset, reversed(actions))
103
class UndoList(SubCommand):
108
List undoable changesets and actions.
112
def process(self, renamer):
113
changesets = list(renamer.history.getChangesets())
114
for cs in changesets:
115
print 'Changeset ID=%d: %s' % (cs.storeID, cs.asHumanly())
116
for a in cs.getActions():
117
print ' Action ID=%d: %s' % (a.storeID, a.asHumanly())
121
print 'No changesets!'
125
class UndoForget(SubCommand):
129
synopsis = '<identifier>'
133
Forget (permanently remove) an undo history action or entire changeset.
134
Consult "undo list" for identifiers.
138
def parseArgs(self, identifier):
139
self['identifier'] = identifier
142
def process(self, renamer):
143
item = getItem(renamer.store, self['identifier'], (Action, Changeset))
144
if not renamer.options['no-act']:
145
logging.msg('Forgetting: %s' % (item.asHumanly(),), verbosity=2)
146
item.deleteFromStore()
154
description = 'Undo previous Renamer actions'
158
Every invocation of Renamer stores the actions taken as a changeset, this
159
allows Renamer to undo entire changesets or previously performed individual
162
Undo actions are communicated by identifiers, which can be discovered by
163
consulting "undo list".
168
('action', None, UndoAction, 'Undo a single action from a changeset'),
169
('changeset', None, UndoChangeset, 'Undo a whole changeset'),
170
('forget', None, UndoForget, 'Forget an undo history item'),
171
('list', None, UndoList, 'List changesets')]
174
def parseArgs(self, *args):
175
raise usage.UsageError('Issue an undo subcommand to perform')