#!/usr/bin/env python3 # vi: encoding=utf-8 ts=8 sts=4 sw=4 et from __future__ import print_function import sys, os sys.path.insert(0, os.environ['HOME']+'/tld-ftp-admin/modules') import ftptree ftptree.quietmode=True from common import checkdir import ftpio import config cval=config.value import curses if len(sys.argv) != 3: print("ERR: wrong number of arguments") print("check-tree.py srctree dsttree") sys.exit(1) checkdir(sys.argv[1]) ftpio.connect('check-tree') if not ftpio.lock(sys.argv[1], True): print("ERR: %s tree already locked" % sys.argv[1]) sys.exit(1) if not ftpio.lock(sys.argv[2], True): ftpio.unlock(sys.argv[1]) print("ERR: %s tree already locked" % sys.argv[2]) sys.exit(1) srctree=ftptree.FtpTree(sys.argv[1], loadall=True) dsttree=ftptree.FtpTree(sys.argv[2]) srctree.checktree(dsttree) # We've loaded all interesting info, so we can continue without locks ftpio.unlock(sys.argv[1]) ftpio.unlock(sys.argv[2]) # The list(set(list)) cast is a fancy way to remove dups from a list names=sorted(list(set([pkg.name for pkg in srctree.values()]))) pkgtree={} for n in names: pkgtree[n]=[] for pkg in srctree.values(): pkgtree[pkg.name].append(pkg) for key in pkgtree.keys(): pkgtree[key]=sorted(pkgtree[key], reverse=True) for pkg in srctree.values(): pkg.marked4movingpool=pkgtree[pkg.name] pkglist=[] for key in sorted(pkgtree.keys()): pkglist=pkglist+pkgtree[key] DoQuit="OMG!" class Screen: def __init__(self, srctreename, dsttreename, elements): self.srctree=srctreename self.dsttree=dsttreename self.elements=elements self.pkglistselected=0 self.pkgliststartpad=0 self.win2startpad=0 self.window=1 try: # initial self.screen=curses.initscr() self.screen.keypad(1) curses.start_color() curses.noecho() curses.cbreak() curses.meta(1) curses.curs_set(0) # Without this refresh(), nothing will show up before first getch() self.screen.refresh() self.__init_colors() self.__init_windows() self.__bind_keys() try: # Main loop while True: if self.window==1: #pkglist self.__redraw_pkglist() self.__redraw_statusbox() elif self.window==2: pass curses.doupdate() self.__handle_input() except DoQuit: pass finally: curses.echo() curses.nocbreak() curses.curs_set(1) curses.endwin() def __bind_keys(self): self.globalkeys=(('qQ', 'quit'), ('KEY_RESIZE', 'resize'), ('KEY_CLOSE', 'quit')) self.perwindowkeys=[(), ()] self.perwindowkeys[0]=(('k', 'move_up'), ('J', 'move_pgdown'), ('K', 'move_pgup'), (' ', 'mark'), ('j', 'move_down'), ('KEY_DOWN', 'move_down'), ('KEY_UP', 'move_up'), ('KEY_HOME', 'move_home'), ('KEY_END', 'move_end'), ('KEY_NPAGE', 'move_pgdown'), ('KEY_PPAGE', 'move_pgup')) def __init_colors(self): curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_CYAN) self.COLOR_TITLEBAR=curses.color_pair(1) curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) self.COLOR_STANDARD=curses.color_pair(2) curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLUE) self.COLOR_ERROR=curses.color_pair(3) curses.init_pair(4, curses.COLOR_YELLOW, curses.COLOR_BLUE) self.COLOR_WARNING=curses.color_pair(4) curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_RED) self.COLOR_ERRORMSG=curses.color_pair(5) curses.init_pair(6, curses.COLOR_WHITE, curses.COLOR_YELLOW) self.COLOR_WARNINGMSG=curses.color_pair(6) curses.init_pair(7, curses.COLOR_BLACK, curses.COLOR_WHITE) self.COLOR_WHITEBG=curses.color_pair(7) def __init_windows(self): self.__set_screen_coordinates() # Titlebar self.titlebar = curses.newpad(1, 200) self.titlebar.bkgdset(ord(' '), self.COLOR_TITLEBAR) self.__redraw_titlebar() # Pkg list pad self.pkglist = curses.newpad(len(self.elements), 200) self.pkglist.bkgdset(ord(' '), self.COLOR_STANDARD) self.pkglist.clrtobot() # Status bar self.statusbar = curses.newpad(1, 200) # Pkg status box self.statusbox = curses.newpad(5, 200) self.statusbox.bkgdset(ord(' '), self.COLOR_STANDARD) self.statusbox.clrtobot() self.__redraw_statusbox() def __set_screen_coordinates(self): self.scr_h, self.scr_w = self.screen.getmaxyx() self.pad_h = self.scr_h-5 self.sbar_y = self.scr_h-4 self.sbox_y = self.scr_h-3 def __redraw_titlebar(self): self.titlebar.clrtobot() # self.titlebar.addstr(0, self.scr_w-14, "tld-ftp-admin") self.titlebar.addstr(0, 1, 'Window #%s' % self.window) tmp="%s => %s" % (self.srctree, self.dsttree) self.titlebar.addstr(0, int(self.scr_w/2-len(tmp)/2)-1, tmp) self.titlebar.addstr(0, self.scr_w-20, "Press 'h' for help.") self.titlebar.noutrefresh(0, 0, 0, 0, 1, self.scr_w-1) def __redraw_statusbox(self): self.statusbox.erase() pkg=self.elements[self.pkglistselected] i=0 for error in pkg.errors: self.statusbox.bkgdset(ord(' '), self.COLOR_ERRORMSG) self.statusbox.addstr(i, 0, 'ERR: '+error, curses.A_BOLD) self.statusbox.bkgdset(ord(' '), self.COLOR_STANDARD) i+=1 for warning in pkg.warnings: self.statusbox.bkgdset(ord(' '), self.COLOR_WARNINGMSG) self.statusbox.addstr(i, 0, 'WARN: '+warning, curses.A_BOLD) self.statusbox.bkgdset(ord(' '), self.COLOR_STANDARD) i+=1 self.statusbox.noutrefresh(0,0,self.sbox_y,0,self.scr_h-1,self.scr_w-1) def __redraw_pkglist(self): # Safety in case there's a bug somewhere if self.pkgliststartpad>len(self.elements)-self.pad_h: self.pkgliststartpad=len(self.elements)-self.pad_h if self.pkgliststartpad<0: self.pkgliststartpad=0 self.pkglist.erase() for i in range(len(self.elements)): if self.elements[i].marked4moving: if self.elements[i].warnings: self.pkglist.bkgdset(ord(' '), self.COLOR_WARNINGMSG) self.pkglist.addstr(i, 0, '+', curses.A_BOLD) else: self.pkglist.bkgdset(ord(' '), self.COLOR_WHITEBG) self.pkglist.addstr(i, 0, '+') if self.elements[i].errors: self.pkglist.bkgdset(ord(' '), self.COLOR_ERROR) elif self.elements[i].warnings: self.pkglist.bkgdset(ord(' '), self.COLOR_WARNING) else: self.pkglist.bkgdset(ord(' '), self.COLOR_STANDARD) if i == self.pkglistselected: self.pkglist.addstr(i, 2, repr(self.elements[i]), curses.A_REVERSE) else: self.pkglist.addstr(i, 2, repr(self.elements[i]), curses.A_BOLD) self.pkglist.bkgdset(ord(' '), self.COLOR_STANDARD) self.pkglist.noutrefresh(self.pkgliststartpad,0,1,0,self.pad_h,self.scr_w-1) def __do_resize(self): self.__set_screen_coordinates() self.__redraw_titlebar() self.__redraw_statusbox() def __do_move_down(self): if 0 <= self.pkglistselected < len(self.elements)-1: self.pkglistselected+=1 if (self.pkgliststartpad!=len(self.elements)-self.pad_h and self.pad_h-(self.pkglistselected-self.pkgliststartpad)<5): self.pkgliststartpad+=1 def __do_move_up(self): if 0 < self.pkglistselected <= len(self.elements)-1: self.pkglistselected-=1 if self.pkgliststartpad!=0 and self.pkglistselected-self.pkgliststartpad<4: self.pkgliststartpad-=1 def __do_move_home(self): self.pkglistselected=0 self.pkgliststartpad=0 def __do_move_end(self): self.pkglistselected=len(self.elements)-1 self.pkgliststartpad=len(self.elements)-self.pad_h def __do_move_pgdown(self): self.pkglistselected+=self.pad_h if self.pkglistselected >= len(self.elements): self.pkglistselected = len(self.elements)-1 self.pkgliststartpad+=self.pad_h if self.pkgliststartpad > len(self.elements)-self.pad_h: self.pkgliststartpad=len(self.elements)-self.pad_h def __do_move_pgup(self): self.pkglistselected-=self.pad_h if self.pkglistselected < 0: self.pkglistselected = 0 self.pkgliststartpad-=self.pad_h if self.pkgliststartpad < 0: self.pkgliststartpad = 0 def __do_quit(self): raise DoQuit() def __do_mark(self): pkg=self.elements[self.pkglistselected] if pkg.errors: return elif pkg.marked4moving: pkg.unmark4moving() else: pkg.mark4moving() def __handle_input(self): key=self.screen.getch() if key==27: # Switch window metakey=self.screen.getch() if 0