]> TLD Linux GIT Repositories - tld-ftp-admin.git/blob - bin/pfa-checktree
- non-integer releases are ok in TLD
[tld-ftp-admin.git] / bin / pfa-checktree
1 #!/usr/bin/env python
2 # vi: encoding=utf-8 ts=8 sts=4 sw=4 et
3
4 import sys, os
5 sys.path.insert(0, os.environ['HOME']+'/tld-ftp-admin/modules')
6 import ftptree
7 ftptree.quietmode=True
8 from common import checkdir
9 import ftpio
10 import config
11 cval=config.value
12
13 import curses
14
15 if len(sys.argv) != 3:
16     print "ERR: wrong number of arguments"
17     print "check-tree.py srctree dsttree"
18     sys.exit(1)
19
20 checkdir(sys.argv[1])
21
22 ftpio.connect('check-tree')
23
24 if not ftpio.lock(sys.argv[1], True):
25     print "ERR: %s tree already locked" % sys.argv[1]
26     sys.exit(1)
27
28 if not ftpio.lock(sys.argv[2], True):
29     ftpio.unlock(sys.argv[1])
30     print "ERR: %s tree already locked" % sys.argv[2]
31     sys.exit(1)
32
33 srctree=ftptree.FtpTree(sys.argv[1], loadall=True)
34 dsttree=ftptree.FtpTree(sys.argv[2])
35
36 srctree.checktree(dsttree)
37
38 # We've loaded all interesting info, so we can continue without locks
39 ftpio.unlock(sys.argv[1])
40 ftpio.unlock(sys.argv[2])
41
42 # The list(set(list)) cast is a fancy way to remove dups from a list
43 names=sorted(list(set([pkg.name for pkg in srctree.values()])))
44
45 pkgtree={}
46
47 for n in names:
48     pkgtree[n]=[]
49
50 for pkg in srctree.values():
51     pkgtree[pkg.name].append(pkg)
52
53 for key in pkgtree.keys():
54     pkgtree[key]=sorted(pkgtree[key], reverse=True)
55
56 for pkg in srctree.values():
57     pkg.marked4movingpool=pkgtree[pkg.name]
58
59 pkglist=[]
60
61 for key in sorted(pkgtree.keys()):
62     pkglist=pkglist+pkgtree[key]
63
64 DoQuit="OMG!"
65
66 class Screen:
67     def __init__(self, srctreename, dsttreename, elements):
68         self.srctree=srctreename
69         self.dsttree=dsttreename
70         self.elements=elements
71         self.pkglistselected=0
72         self.pkgliststartpad=0
73         self.win2startpad=0
74         self.window=1
75         try:
76             # initial
77             self.screen=curses.initscr()
78             self.screen.keypad(1)
79             curses.start_color()
80             curses.noecho()
81             curses.cbreak()
82             curses.meta(1)
83             curses.curs_set(0)
84
85              # Without this refresh(), nothing will show up before first getch()
86             self.screen.refresh()
87
88             self.__init_colors()
89             self.__init_windows()
90             self.__bind_keys()
91
92             try:
93                 # Main loop
94                 while True:
95                     if self.window==1: #pkglist
96                         self.__redraw_pkglist()
97                         self.__redraw_statusbox()
98                     elif self.window==2: 
99                         pass
100                     curses.doupdate()
101                     self.__handle_input()
102             except DoQuit:
103                 pass
104         finally:
105             curses.echo()
106             curses.nocbreak()
107             curses.curs_set(1)
108             curses.endwin()
109
110     def __bind_keys(self):
111         self.globalkeys=(('qQ', 'quit'), ('KEY_RESIZE', 'resize'),
112                 ('KEY_CLOSE', 'quit'))
113         self.perwindowkeys=[(), ()]
114         self.perwindowkeys[0]=(('k', 'move_up'), ('J', 'move_pgdown'),
115                 ('K', 'move_pgup'), (' ', 'mark'), ('j', 'move_down'),
116                 ('KEY_DOWN', 'move_down'), ('KEY_UP', 'move_up'),
117                 ('KEY_HOME', 'move_home'), ('KEY_END', 'move_end'),
118                 ('KEY_NPAGE', 'move_pgdown'), ('KEY_PPAGE', 'move_pgup'))
119                 
120
121     def __init_colors(self):
122         curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN)
123         self.COLOR_TITLEBAR=curses.color_pair(1)
124         curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE)
125         self.COLOR_STANDARD=curses.color_pair(2)
126         curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLUE)
127         self.COLOR_ERROR=curses.color_pair(3)
128         curses.init_pair(4, curses.COLOR_YELLOW, curses.COLOR_BLUE)
129         self.COLOR_WARNING=curses.color_pair(4)
130         curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_RED)
131         self.COLOR_ERRORMSG=curses.color_pair(5)
132         curses.init_pair(6, curses.COLOR_WHITE, curses.COLOR_YELLOW)
133         self.COLOR_WARNINGMSG=curses.color_pair(6)
134         curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_WHITE)
135         self.COLOR_WHITEBG=curses.color_pair(7)
136
137     def __init_windows(self):
138         self.__set_screen_coordinates()
139
140         # Titlebar
141         self.titlebar = curses.newpad(1, 200)
142         self.titlebar.bkgdset(ord(' '), self.COLOR_TITLEBAR)
143         self.__redraw_titlebar()
144
145         # Pkg list pad
146         self.pkglist = curses.newpad(len(self.elements), 200)
147         self.pkglist.bkgdset(ord(' '), self.COLOR_STANDARD)
148         self.pkglist.clrtobot()
149
150         # Status bar
151         self.statusbar = curses.newpad(1, 200)
152
153         # Pkg status box
154         self.statusbox = curses.newpad(5, 200)
155         self.statusbox.bkgdset(ord(' '), self.COLOR_STANDARD)
156         self.statusbox.clrtobot()
157         self.__redraw_statusbox()
158
159     def __set_screen_coordinates(self):
160         self.scr_h, self.scr_w = self.screen.getmaxyx()
161         self.pad_h = self.scr_h-5
162         self.sbar_y = self.scr_h-4
163         self.sbox_y = self.scr_h-3
164
165     def __redraw_titlebar(self):
166         self.titlebar.clrtobot()
167 #        self.titlebar.addstr(0, self.scr_w-14, "tld-ftp-admin")
168         self.titlebar.addstr(0, 1, 'Window #%s' % self.window)
169         tmp="%s => %s" % (self.srctree, self.dsttree)
170         self.titlebar.addstr(0, int(self.scr_w/2-len(tmp)/2)-1, tmp)
171         self.titlebar.addstr(0, self.scr_w-20, "Press 'h' for help.")
172         self.titlebar.noutrefresh(0, 0, 0, 0, 1, self.scr_w-1)
173
174     def __redraw_statusbox(self):
175         self.statusbox.erase()
176         pkg=self.elements[self.pkglistselected]
177         i=0
178         for error in pkg.errors:
179             self.statusbox.bkgdset(ord(' '), self.COLOR_ERRORMSG)
180             self.statusbox.addstr(i, 0, 'ERR: '+error, curses.A_BOLD)
181             self.statusbox.bkgdset(ord(' '), self.COLOR_STANDARD)
182             i+=1
183         for warning in pkg.warnings:
184             self.statusbox.bkgdset(ord(' '), self.COLOR_WARNINGMSG)
185             self.statusbox.addstr(i, 0, 'WARN: '+warning, curses.A_BOLD)
186             self.statusbox.bkgdset(ord(' '), self.COLOR_STANDARD)
187             i+=1
188         self.statusbox.noutrefresh(0,0,self.sbox_y,0,self.scr_h-1,self.scr_w-1)
189
190     def __redraw_pkglist(self):
191         # Safety in case there's a bug somewhere
192         if self.pkgliststartpad>len(self.elements)-self.pad_h:
193             self.pkgliststartpad=len(self.elements)-self.pad_h
194         if self.pkgliststartpad<0:
195             self.pkgliststartpad=0
196
197         self.pkglist.erase()
198         for i in range(len(self.elements)):
199             if self.elements[i].marked4moving:
200                 if self.elements[i].warnings:
201                     self.pkglist.bkgdset(ord(' '), self.COLOR_WARNINGMSG)
202                     self.pkglist.addstr(i, 0, '+', curses.A_BOLD)
203                 else:
204                     self.pkglist.bkgdset(ord(' '), self.COLOR_WHITEBG)
205                     self.pkglist.addstr(i, 0, '+')
206
207             if self.elements[i].errors:
208                 self.pkglist.bkgdset(ord(' '), self.COLOR_ERROR)
209             elif self.elements[i].warnings:
210                 self.pkglist.bkgdset(ord(' '), self.COLOR_WARNING)
211             else:
212                 self.pkglist.bkgdset(ord(' '), self.COLOR_STANDARD)
213             if i == self.pkglistselected:
214                 self.pkglist.addstr(i, 2, `self.elements[i]`, curses.A_REVERSE)
215             else:
216                 self.pkglist.addstr(i, 2, `self.elements[i]`, curses.A_BOLD)
217             self.pkglist.bkgdset(ord(' '), self.COLOR_STANDARD)
218         self.pkglist.noutrefresh(self.pkgliststartpad,0,1,0,self.pad_h,self.scr_w-1)
219
220     def __do_resize(self):
221         self.__set_screen_coordinates()
222         self.__redraw_titlebar()
223         self.__redraw_statusbox()
224
225     def __do_move_down(self):
226         if 0 <= self.pkglistselected < len(self.elements)-1:
227             self.pkglistselected+=1
228             if (self.pkgliststartpad!=len(self.elements)-self.pad_h and
229                 self.pad_h-(self.pkglistselected-self.pkgliststartpad)<5):
230                 self.pkgliststartpad+=1
231
232     def __do_move_up(self):
233         if 0 < self.pkglistselected <= len(self.elements)-1:
234             self.pkglistselected-=1
235             if self.pkgliststartpad!=0 and self.pkglistselected-self.pkgliststartpad<4:
236                 self.pkgliststartpad-=1
237
238     def __do_move_home(self):
239         self.pkglistselected=0
240         self.pkgliststartpad=0
241
242     def __do_move_end(self):
243         self.pkglistselected=len(self.elements)-1
244         self.pkgliststartpad=len(self.elements)-self.pad_h
245
246     def __do_move_pgdown(self):
247         self.pkglistselected+=self.pad_h
248         if self.pkglistselected >= len(self.elements):
249             self.pkglistselected = len(self.elements)-1
250         self.pkgliststartpad+=self.pad_h
251         if self.pkgliststartpad > len(self.elements)-self.pad_h:
252             self.pkgliststartpad=len(self.elements)-self.pad_h
253
254     def __do_move_pgup(self):
255         self.pkglistselected-=self.pad_h
256         if self.pkglistselected < 0:
257             self.pkglistselected = 0
258         self.pkgliststartpad-=self.pad_h
259         if self.pkgliststartpad < 0:
260             self.pkgliststartpad = 0
261
262     def __do_quit(self):
263         raise DoQuit
264
265     def __do_mark(self):
266         pkg=self.elements[self.pkglistselected]
267         if pkg.errors:
268             return
269         elif pkg.marked4moving:
270             pkg.unmark4moving()
271         else:
272             pkg.mark4moving()
273
274     def __handle_input(self):
275         key=self.screen.getch()
276         if key==27:
277             # Switch window
278             metakey=self.screen.getch()
279             if 0<metakey<256:
280                 c=chr(metakey)
281                 if c=='1':
282                     self.window=1
283                 elif c=='2':
284                     self.window=2
285         elif 0<key<256:
286             c=chr(key)
287             for bind in self.globalkeys+self.perwindowkeys[self.window-1]:
288                 if not bind[0].startswith('KEY_') and c in bind[0]:
289                     exec 'self._Screen__do_%s()' % bind[1]
290
291         else:
292 #            self.elements[0]=`key`
293             for bind in self.globalkeys+self.perwindowkeys[self.window-1]:
294                 if bind[0].startswith('KEY_'):
295                     if key == getattr(curses, bind[0]):
296                         exec 'self._Screen__do_%s()' % bind[1]
297
298 s = Screen(sys.argv[1], sys.argv[2], pkglist)
299