From 509a236c5efe1c9cae652ec9fb4e471b92754ae0 Mon Sep 17 00:00:00 2001 From: simonpauw Date: Fri, 22 Jun 2018 10:02:45 +0200 Subject: [PATCH] Added restore50 to bin. This script restores deleted files. # restore50 This script can restore deleted files in a Cloud9 workspace. This only works for files that you edited in the cloud9 editor. It mines the versioning database and looks for files that are in this database but not in the file system. # Example usage $ restore50 The following files can be restored: file# | last modified | filename ------|----------------|------------------------------------------ 0 | (Wed 02-14-18) | ~/workspace/pset1/some-file-I-deleted.c 1 | (Wed 04-04-18) | ~/workspace/pset1/some-other-file-I-deleted.c ------------------------------------------------------------------ Enter file# to restore (or anything else to quit): 0 Restored ~/workspace/pset1/some-file-I-deleted.c ------------------------------------------------------------------ Enter file# to restore (or anything else to quit): q 1 file restored --- files/usr/bin/restore50 | 118 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 files/usr/bin/restore50 diff --git a/files/usr/bin/restore50 b/files/usr/bin/restore50 new file mode 100644 index 0000000..f6e30c3 --- /dev/null +++ b/files/usr/bin/restore50 @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +# restore: restore (undelete) files from the cloud9 versioning database +# created by Simon Pauw, May 2018 + +# installation: +# chmod a+x restore +# mv ./restore ~/bin/restore + +# example: +# $ restore +# The following files can be restored: +# +# file# | last modified | filename +# ------|----------------|------------------------------------------ +# 0 | (Wed 02-14-18) | ~/workspace/pset1/some-file-I-deleted.c +# 1 | (Wed 04-04-18) | ~/workspace/pset1/some-other-file-I-deleted.c +# ------------------------------------------------------------------ +# Enter file# to restore (or anything else to quit): 0 +# Restored ~/workspace/pset1/some-file-I-deleted.c +# ------------------------------------------------------------------ +# Enter file# to restore (or anything else to quit): q +# 1 file restored + +import sqlite3 +from pathlib import Path, PurePath +import os +import sys +import shutil +import datetime + + +def main(): + # locate the versioning database + db_file = str(get_db_path()) + + # open versioning db + connection = sqlite3.connect(db_file) + cursor = connection.cursor() + + # retrieve and list all missing files + print("The following files can be restored:") + print() + print("file# | last modified | filename") + print("------|----------------|------------------------------------------") + deleted_files = [] + file_number = 0 + + # get files from db and sort by date + files = list(cursor.execute('''SELECT * from Documents''')) + files.sort(key = lambda x: x[8]) + + # display all files that do not exist in file system + for row in files: + fname = full_path(row[1]) + if not fname.exists(): + deleted_files.append(row) + print("{:5n} | ({:12s}) | ~/workspace/{}".format(file_number, pretty_time(row[8]), row[1])) + file_number += 1 + + # close db + connection.close() + + restored = [] + while True: + # get file to restore + print("------------------------------------------------------------------") + inp = input("Enter file# to restore (or anything else to quit): ") + try: + filenumber = int(inp) + except ValueError: + quit(len(restored)) + if filenumber >= len(deleted_files) or filenumber < 0: + print("File number {} is not valid".format(filenumber)) + else: + # restore + file_entry = deleted_files[filenumber] + if filenumber in restored: + print("File ~/workspace/{} is already restored.".format(file_entry[1])) + else: + restored.append(filenumber) + path = full_path(file_entry[1]) + # restore dir if needed + path.parent.mkdir(parents=True, exist_ok=True) + # write last contents back to file + path.write_bytes(file_entry[2]) + print("Restored ~/workspace/{}".format(file_entry[1])) + +def get_db_path(): + # find db file (~/.c9/somenumber/collab.db) + c9path = Path(Path.home(), '.c9') + for p in c9path.iterdir(): + try: + i = int(str(p.stem)) + full_db_path = Path(p, 'collab.db') + if(full_db_path.exists()): + return full_db_path + except ValueError: + pass + return None + +def full_path(rel_path): + return Path(Path.home(), 'workspace', rel_path) + +weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] +def pretty_time(time): + time = datetime.datetime.strptime(time,'%Y-%m-%d %H:%M:%S') + today = datetime.date.today() + if(time.date() == today): + return "today, " + time.strftime('%H:%M') + return "{} {}".format(weekday[time.weekday()], time.strftime('%m-%d-%y')) + +def quit(n): + print("{} file{} restored".format("No" if n < 1 else n, "" if n == 1 else "s")) + return sys.exit() + +if __name__ == "__main__": + main()