Last active
May 10, 2022 06:44
-
-
Save mnieber/774e868e96d3cdb16eeec3c1982abb19 to your computer and use it in GitHub Desktop.
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/env python | |
# -*- coding: utf-8 -*- | |
# The purpose of this script is to use a "local" git-directory alongside | |
# a "main" git working directory, and keep the two in sync. The "local" directory | |
# is used for storing local files that are associated with the "main" files but cannot | |
# be stored in the "main" directory (for example, local editor config files). | |
# | |
# Synopsis: | |
# | |
# // Create local directory with a file. This creates a .git-local.json file in the | |
# // main directory. | |
# git local init | |
# touch .git-local/my-editor.config | |
# git local save | |
# | |
# // Commit the .git-local.json file to the main directory. | |
# git add .git-local.json | |
# git commit -m "Add .git-local.json" | |
# | |
# // Switch to a different branch in the main directory, and change the local files | |
# // to suit the needs for working with that branch | |
# git checkout -b experimental-branch | |
# echo "split-window=1" >> .git-local/my-editor.config | |
# git local save // This step updates .git-local.json in the main directory | |
# git add .git-local.json | |
# git commit -m "Update .git-local.json" | |
# | |
# // Switch back to the main branch | |
# git checkout main | |
# | |
# // Update the local files to reflect that we are now on the main branch. | |
# // Do this step whenever you switch between "main" and "experimental" | |
# git local load | |
# | |
# | |
# Note: place this script on the path, so git can find it, | |
# and make it executable (chmod +x git-fixdown). | |
# | |
# Author: Maarten Nieber | |
# Url: https://gist.github.com/mnieber/774e868e96d3cdb16eeec3c1982abb19 | |
# | |
import argparse | |
import json | |
import os | |
import subprocess | |
import sys | |
def git(*args, cwd="."): | |
pipes = subprocess.Popen( | |
["git"] + list(args), stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd | |
) | |
std_out, std_err = pipes.communicate() | |
if pipes.returncode != 0: | |
print(std_out) | |
print(std_err.strip()) | |
sys.exit(pipes.returncode) | |
result = std_out.decode("utf-8") | |
if result.endswith("\n"): | |
result = result[:-1] | |
return result | |
def load_json(fn): | |
with open(fn, "r") as f: | |
return json.load(f) | |
def save_json(data, fn): | |
with open(fn, "w") as f: | |
json.dump(data, f) | |
def add_line_to_file(fn, line): | |
with open(fn, "a") as f: | |
f.write(line + "\n") | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser() | |
parser.add_argument("command", choices=["init", "save", "load"]) | |
args = parser.parse_args() | |
user_name = git("config", "user.name") | |
main_repo_dir = git("rev-parse", "--show-toplevel") | |
main_repo_sha = git("rev-parse", "HEAD") | |
branch_name = git("rev-parse", "--abbrev-ref", "HEAD") | |
local_dir = os.path.join(main_repo_dir, ".git-local") | |
local_gitignore_file = os.path.join(local_dir, ".gitignore") | |
local_git_dir = os.path.join(local_dir, ".git") | |
local_files_json_fn = os.path.join(main_repo_dir, ".git-local.json") | |
lut = load_json(local_files_json_fn) if os.path.exists(local_files_json_fn) else {} | |
if args.command == "init": | |
os.makedirs(local_dir) | |
if not os.path.exists(local_git_dir): | |
git("init", cwd=local_dir) | |
add_line_to_file(local_gitignore_file, f"") | |
if args.command in ("save", "init"): | |
if git("status", "--porcelain", cwd=local_dir): | |
git("add", "-A", cwd=local_dir) | |
git("commit", "-m", f"{branch_name}: Save local files", cwd=local_dir) | |
local_files_sha = git("rev-parse", "HEAD", cwd=local_dir) | |
if lut[user_name] != local_files_sha: | |
lut[user_name] = local_files_sha | |
save_json(lut, local_files_json_fn) | |
print("M .git-local.json") | |
if args.command == "load": | |
if git("status", "--porcelain", cwd=local_dir) and not args.force: | |
print("Local files are not clean. Please commit or stash them first.") | |
sys.exit(1) | |
local_files_sha = lut.get(user_name) | |
if not local_files_sha: | |
print(f"No local files found for user {user_name}") | |
sys.exit(1) | |
git("revert", "--no-commit", f"{local_files_sha}..HEAD", cwd=local_dir) | |
git("commit", "-m", f"{branch_name}: Load local files", cwd=local_dir) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment