This repository has been archived on 2025-03-31. You can view files and clone it, but cannot push or open issues or pull requests.
svnreview/svnreview.py

177 lines
5.0 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import curses
import logging
#globals
currentLine = 0
page = 0
err = None
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(message)s',
filename='/tmp/svnreview.log',
filemode='w')
def getFileList():
fileList = []
for line in os.popen("svn status").read().splitlines():
status = line[0:7].strip()
if status == "?":
# ignore files that aren't in version control
continue
file = line[7:].strip()
fileList.append({"status" : status, "file" : file, "checked" : False})
return fileList
#def getFileList():
# fileList = list()
# for i in range(0,200):
# fileList.append({"status": "M", "file":"/cosmo/blah" + str(i), "checked": False})
# return fileList
#init curses
def initCurses():
global stdscr
global pad
stdscr = curses.initscr()
curses.start_color()
curses.use_default_colors()
curses.noecho()
curses.cbreak()
stdscr.keypad(1)
pad = curses.newpad(1000, 1000)
#clean up
def cleanupCurses():
curses.nocbreak()
stdscr.keypad(0)
curses.echo()
curses.endwin()
end_buffer_size = 3
def getMaxLines():
return stdscr.getmaxyx()[0] - end_buffer_size
line_format = "[%(checkmark)s] %(status)-6s %(file)s"
help_string1 = "q - quit | a - check all | up/down - move one line"
help_string2 = "space - check/uncheck | u - uncheck all | right/left - page up/down"
def redraw():
global err
global page
maxLines = getMaxLines()
page = currentLine // maxLines
start = page * maxLines
stdscr.erase()
for linenumber, fileinfo in enumerate(filelist[start:start + maxLines]):
if fileinfo['checked']:
fileinfo['checkmark'] = 'x'
else:
fileinfo['checkmark'] = ' '
try:
stdscr.addstr(linenumber, 0, line_format % fileinfo, curses.A_BOLD)
except Exception as err:
logging.error(err)
if len(filelist) == 0:
stdscr.addstr(0, 0, "No files changes - press 'q' to quit", curses.A_BOLD)
else:
stdscr.addstr(maxLines + 1, 0, help_string1, curses.A_DIM)
stdscr.addstr(maxLines + 2, 0, help_string2, curses.A_DIM)
def toggleChecked(index):
checked = filelist[index]["checked"]
filelist[index]["checked"] = not checked
def checkall(checked=True):
for file in filelist:
file["checked"] = checked
def move(amount):
global currentLine
if (amount + currentLine < 0):
currentLine = 0
elif (amount + currentLine > (len(filelist) - 1)):
currentLine = len(filelist) - 1
else:
currentLine = currentLine + amount
redraw()
positionCursor()
def positionCursor():
stdscr.move((currentLine % getMaxLines()) ,1)
def gotoPage(newPage):
newLine = newPage * getMaxLines() + (currentLine % getMaxLines())
move(newLine - currentLine)
redraw()
positionCursor()
def main():
global stdscr
try:
global filelist
# get the file list before initCurses, because opening a pipe
# after curses is initialized causes Cygwin to hang
filelist = getFileList()
initCurses()
redraw()
y,x = curses.getsyx()
stdscr.move(0,1)
while 1:
c = stdscr.getch()
logging.debug(c)
if c == ord('q'): break # Exit the while()
elif c == curses.KEY_UP:
logging.debug("KEYUP!")
move(-1)
elif c == curses.KEY_DOWN :
logging.debug("KEYDOWN")
move(1)
elif c == ord(' '):
logging.debug("SPACE")
toggleChecked(currentLine)
move(1)
elif c == ord('a'):
y,x = curses.getsyx()
checkall()
redraw()
stdscr.move(y,x)
elif c == ord('u'):
y,x = curses.getsyx()
checkall(False)
redraw()
stdscr.move(y,x)
elif c == curses.KEY_RIGHT:
logging.debug("KEY_RIGHT")
move(getMaxLines())
elif c == curses.KEY_LEFT:
logging.debug("KEY_LEFT")
move(-getMaxLines())
elif c == curses.KEY_ENTER or c == 10:
logging.debug("KEY_ENTER")
curses.def_prog_mode()
curses.endwin()
os.system('clear && svn diff "' + filelist[currentLine]["file"] + '" --diff-cmd=colordiff | less -r')
stdscr.refresh()
elif 0 <= c <= 256 and chr(c).isdigit():
destination = 10
if chr(c) != 0:
destination = int(chr(c)) - 1
gotoPage(destination)
except Exception as err:
logging.error(err)
cleanupCurses()
print(' '.join(f["file"] for f in filelist if f["checked"]))
if __name__ == "__main__":
main()