nixos-dotfiles/scripts/update_git.py

183 lines
5.1 KiB
Python

#!/usr/bin/env python3
from git import Repo
from git import Actor
import shutil
import os
WORKING_DIR = "/tmp/push-dotfiles"
GIT_REPO_URL = "git@git.seanomik.net:SeanOMik/nixos-dotfiles.git"
## Get a yes or no answer from the user and handle invalid input
def get_yes_no_answer(question: str, error_msg: str = "ERROR: Malformed input!"):
ans = ""
while ans != "y" or ans != "n":
print(f"{question} (y,n): ", end="")
ans = input()
if ans != "y" or ans != "n":
print(error_msg)
if ans == "y":
return True
elif ans == "n":
return False
## Clears the working directory
def remove_working_dir():
if os.path.exists(WORKING_DIR):
shutil.rmtree(WORKING_DIR)
print(f"Removed working directory ({WORKING_DIR}).")
else:
print(f"Skipping deletion of working directory since it doesn't exist.")
## Copy the dotfiles (/etc/nixos) to the working directory
def copy_dotfiles():
src_directory = "/etc/nixos"
for filename in os.listdir(src_directory):
if filename == ".git":
continue
else:
full_path = os.path.join(src_directory, filename)
if os.path.isdir(full_path):
shutil.copytree(full_path, os.path.join(WORKING_DIR, filename))
else:
shutil.copy(full_path, WORKING_DIR)
print("Copied \"/etc/nixos\" dotfiles to working directory.")
## Clone the git repository to the working dir
def clone_git_repo():
print("Cloning git repository...")
Repo.clone_from(GIT_REPO_URL, WORKING_DIR)
print("Cloned git repository!")
## Clear the working directory
def clear_working_dir():
for filename in os.listdir(WORKING_DIR):
if filename == ".git" or filename.endswith(".py") or filename == "shell.nix":
continue
else:
full_path = os.path.join(WORKING_DIR, filename)
if os.path.isdir(full_path):
shutil.rmtree(full_path)
else:
os.remove(full_path)
print("Cleared git repo...")
## Get the git repository in the working dir
def get_git_repo():
return Repo(WORKING_DIR)
## Stage changes
def stage_git_changes(repo: Repo):
file_diff_list = []
# TODO: Check for the staged changes also
diff = repo.index.diff(None)
if len(diff) == 0:
diff = repo.index.diff("HEAD")
if len(diff) == 0:
print("ERROR: No changes have been made!")
exit()
else:
print("All changes are already staged...")
return
print("Git diff:")
for item in diff:
if item.deleted_file:
print(f" D - {item.a_path}")
file_diff_list.append(os.path.join(repo.working_tree_dir, item.a_path))
elif item.new_file:
print(f" N - {item.b_path}")
file_diff_list.append(os.path.join(repo.working_tree_dir, item.b_path))
elif item.renamed_file:
print(f" R - {item.a_path} to {item.b_path}")
file_diff_list.append(os.path.join(repo.working_tree_dir, item.b_path))
else:
print(f" C - {item.a_path}")
file_diff_list.append(os.path.join(repo.working_tree_dir, item.a_path))
ans = get_yes_no_answer("Stage entire diff?")
if ans:
for diff in file_diff_list:
repo.git.add(diff)
print("Staged all changes")
else:
print("TODO: Create numbered list to only stage certain files") # TODO
## Get the author from the user
def get_git_author(repo: Repo):
ans = get_yes_no_answer("Use git config user?")
if ans:
username = repo.config_reader().get_value("user", "name")
email = repo.config_reader().get_value("user", "email")
print(f"Got git author:\n Username: {username}\n Email: {email}")
ans = get_yes_no_answer("Is this author correct?")
if ans:
return Actor(username, email)
else:
return get_git_author(repo)
else:
print("Enter username: ", end="")
username = input()
print("Enter email: ", end="")
email = input()
return Actor(username, email)
## Commit changes
def commit_changes(repo: Repo, message: str, author: Actor):
res = repo.git.commit('-S', '-m', f'"{message}"', author=f'"{author.name} <{author.email}>"')
print(res)
print("Committed changes!")
## Push git changes to the repo!
def push_git_changes():
repo = get_git_repo()
stage_git_changes(repo)
ans = ""
while len(ans) == 0:
print("Commit message: ", end="")
ans = input()
if len(ans) == 0:
print("ERROR: Cannot use an empty commit message!")
commit_changes(repo, ans, get_git_author(repo))
# Actually push now
print("Pushing changes...")
origin = repo.remote(name='origin')
origin.push()
print("Pushed changes!")
def main():
remove_working_dir();
clone_git_repo();
clear_working_dir();
copy_dotfiles();
#push_git_changes();
print("Done!")
if __name__ == '__main__':
main()