-
-
Save joe42/984fb415942b67ddf70f to your computer and use it in GitHub Desktop.
Stash all modified files, not just their changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2.7 | |
from git import Repo | |
import tempfile | |
import shutil | |
import sys | |
import os | |
import shelve | |
import errno | |
from os.path import join as joinpath | |
from os.path import dirname, basename | |
command = sys.argv[1] | |
stash_name = "" | |
if command != "list": | |
stash_name = sys.argv[2] | |
BACKUPDIR = os.path.expanduser("~/.git_modified_files") | |
def mkdir_p(path): | |
try: | |
os.makedirs(path) | |
except OSError as exc: # Python >2.5 | |
if exc.errno == errno.EEXIST and os.path.isdir(path): | |
pass | |
else: | |
raise | |
def get_untracked(repo): | |
return repo.git.ls_files("--exclude-standard", "--others").splitlines() | |
def gitstash(command, stash_name): | |
repo = Repo(os.path.curdir) | |
backup_modified_files_dir = joinpath(BACKUPDIR, repo.git_dir[1:])) | |
session_dir = joinpath(backup_modified_files_dir, stash_name) | |
session_files_dir = joinpath(session_dir, "files") | |
session_files_dict = joinpath(session_dir,"files_dict") | |
mkdir_p(session_files_dir) | |
realpath_to_tmpfile_map = shelve.open(session_files_dict) | |
if command == "list": | |
for stash_name in os.listdir(backup_modified_files_dir): | |
if stash_name != "files" and stash_name != "files_dict": | |
print(stash_name) | |
exit(0) | |
if command == "drop": | |
shutil.rmtree(session_dir) | |
print("Dropped stash "+stash_name+".") | |
exit(0) | |
if command == "apply" or command == "pop": | |
# TODO: Do not overwrite files that are not yet under version control. | |
for (realpath, temppath) in realpath_to_tmpfile_map.items(): | |
absolute_realpath = joinpath(repo.working_dir, realpath) | |
mkdir_p(dirname(absolute_realpath)) | |
shutil.copy(temppath, absolute_realpath) | |
if command == "pop": | |
shutil.rmtree(session_dir) | |
print("Popped stash "+stash_name+".") | |
else: | |
print("Applied stash "+stash_name+".") | |
exit(0) | |
if command == "stash": | |
for untracked in get_untracked(repo): | |
tmpfile = tempfile.NamedTemporaryFile(dir=session_files_dir,prefix=basename(untracked)).name | |
realpath_to_tmpfile_map[untracked] = tmpfile | |
# print(untracked+" --> "+tmpfile) | |
shutil.move(joinpath(repo.working_dir, untracked), tmpfile) | |
for diff in repo.head.commit.diff(None): | |
if diff.deleted_file: | |
continue | |
tmpfile = tempfile.NamedTemporaryFile(dir=session_files_dir,prefix=diff.b_blob.name).name | |
realpath_to_tmpfile_map[diff.b_blob.path] = tmpfile | |
# print(diff.b_blob.path+" --> "+tmpfile) | |
shutil.copy(joinpath(repo.working_dir, diff.b_blob.path), tmpfile) | |
try: | |
repo.git.reset("--hard") | |
except Exception, e: | |
print(e) | |
realpath_to_tmpfile_map.sync() | |
realpath_to_tmpfile_map.close() | |
if __name__ == '__main__': | |
gitstash(command, stash_name) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment