tweak git and ssh
This commit is contained in:
parent
3941a8d2ac
commit
dd7d702010
@ -47,3 +47,5 @@
|
|||||||
[credential "https://gist.github.com"]
|
[credential "https://gist.github.com"]
|
||||||
helper =
|
helper =
|
||||||
helper = !/usr/bin/gh auth git-credential
|
helper = !/usr/bin/gh auth git-credential
|
||||||
|
[push]
|
||||||
|
autoSetupRemote = true
|
||||||
|
@ -52,3 +52,7 @@ export SDKMAN_DIR="$HOME/.sdkman"
|
|||||||
|
|
||||||
# Flutter
|
# Flutter
|
||||||
[[ -s "$HOME/pkg/flutter/bin" ]] && export PATH="$HOME/pkg/flutter/bin:$PATH"
|
[[ -s "$HOME/pkg/flutter/bin" ]] && export PATH="$HOME/pkg/flutter/bin:$PATH"
|
||||||
|
|
||||||
|
# Rye
|
||||||
|
[[ -s "$HOME/.rye/env" ]] && source "$HOME/.rye/env"
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
@ -5,6 +5,7 @@ Host * !*.github.com !github.com
|
|||||||
IdentityFile %d/.ssh/id_ed25519
|
IdentityFile %d/.ssh/id_ed25519
|
||||||
IdentityFile %d/.ssh/id_rsa
|
IdentityFile %d/.ssh/id_rsa
|
||||||
# VisualHostKey yes
|
# VisualHostKey yes
|
||||||
|
VerifyHostKeyDNS ask
|
||||||
|
|
||||||
# Github SSH adapter for restricted networks
|
# Github SSH adapter for restricted networks
|
||||||
Host github.com gist.github.com
|
Host github.com gist.github.com
|
||||||
@ -91,6 +92,8 @@ Host td-prod td-prod2 td-prod3 td-prod4
|
|||||||
User guru
|
User guru
|
||||||
Host w6421
|
Host w6421
|
||||||
User "guru-domain\\epratten"
|
User "guru-domain\\epratten"
|
||||||
|
#RequestTTY yes
|
||||||
|
# RemoteCommand "C:\Program Files\Git\bin\bash.exe" --login
|
||||||
|
|
||||||
# Personal Infra
|
# Personal Infra
|
||||||
Host oci-arm
|
Host oci-arm
|
||||||
|
6
scripts/git-detect-fake-authors
Executable file
6
scripts/git-detect-fake-authors
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
# This script finds every time someone makes a commit under someone else's name
|
||||||
|
# NOTE: This includes co-authoring
|
||||||
|
set -e
|
||||||
|
|
||||||
|
git-log-sqlite -q 'SELECT committer as Real, author as Fake, count(*) as Count FROM commits WHERE author NOT LIKE committer GROUP BY author, committer ORDER BY count DESC;'
|
182
scripts/git-log-sqlite
Executable file
182
scripts/git-log-sqlite
Executable file
@ -0,0 +1,182 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
import subprocess
|
||||||
|
import sqlite3
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
FIELDS = {
|
||||||
|
"ct": "timestamp",
|
||||||
|
"aN": "author",
|
||||||
|
"aE": "email",
|
||||||
|
"cN": "committer",
|
||||||
|
"cE": "committer_email",
|
||||||
|
"s": "subject",
|
||||||
|
"b": "body",
|
||||||
|
"N": "notes",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def read_properties() -> Dict[str, Dict[str, str]]:
|
||||||
|
output = {}
|
||||||
|
for field in FIELDS:
|
||||||
|
# Construct the log request
|
||||||
|
format_str = f"%H %{field}%x00"
|
||||||
|
|
||||||
|
# Get the results
|
||||||
|
repo_results = subprocess.run(
|
||||||
|
["git", "log", f"--format=format:{format_str}"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
).stdout
|
||||||
|
submodule_results = subprocess.run(
|
||||||
|
[
|
||||||
|
"git",
|
||||||
|
"submodule",
|
||||||
|
"foreach",
|
||||||
|
"git",
|
||||||
|
"log",
|
||||||
|
f"--format=format:{format_str}",
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
).stdout
|
||||||
|
|
||||||
|
# Parse the results
|
||||||
|
all_results = repo_results + submodule_results
|
||||||
|
all_results = all_results.split("\x00")
|
||||||
|
for result in all_results:
|
||||||
|
if " " not in result or result == "":
|
||||||
|
continue
|
||||||
|
commit_hash, value = result.split(" ", 1)
|
||||||
|
if commit_hash.startswith("Entering"):
|
||||||
|
continue
|
||||||
|
if commit_hash.startswith("\n"):
|
||||||
|
commit_hash = commit_hash[1:]
|
||||||
|
if commit_hash not in output:
|
||||||
|
output[commit_hash] = {}
|
||||||
|
output[commit_hash][field] = value
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
def create_table(cursor: sqlite3.Cursor) -> None:
|
||||||
|
sql = "CREATE TABLE IF NOT EXISTS commits (hash TEXT PRIMARY KEY, "
|
||||||
|
for field in FIELDS.values():
|
||||||
|
ty = "TEXT"
|
||||||
|
if field == "timestamp":
|
||||||
|
ty = "INTEGER"
|
||||||
|
if field == "hash":
|
||||||
|
ty = "TEXT PRIMARY KEY"
|
||||||
|
|
||||||
|
sql += f"{field} {ty}, "
|
||||||
|
sql = sql[:-2] + ")"
|
||||||
|
logger.debug(f"Creating table with SQL: {sql}")
|
||||||
|
cursor.execute(sql)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
# Handle program arguments
|
||||||
|
ap = argparse.ArgumentParser(
|
||||||
|
prog="git-log-sqlite", description="Interact with the git log using SQL"
|
||||||
|
)
|
||||||
|
ap.add_argument(
|
||||||
|
"--dump",
|
||||||
|
help="Path to a sqlite3 database file to dump contents to. DELETES EXISTING FILE",
|
||||||
|
type=Path,
|
||||||
|
)
|
||||||
|
ap.add_argument(
|
||||||
|
"--interactive",
|
||||||
|
"-i",
|
||||||
|
help="Start an interactive SQL session",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
ap.add_argument("--query", "-q", help="Run a query and print the results")
|
||||||
|
ap.add_argument("--no-header", help="Do not print the header", action="store_true")
|
||||||
|
ap.add_argument("--mode", help="Set the mode for the sqlite3 command", default="table")
|
||||||
|
ap.add_argument(
|
||||||
|
"-v", "--verbose", help="Enable verbose logging", action="store_true"
|
||||||
|
)
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.DEBUG if args.verbose else logging.INFO,
|
||||||
|
format="%(levelname)s: %(message)s",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Interactive mode and query mode are mutually exclusive
|
||||||
|
if args.interactive and args.query:
|
||||||
|
logger.error("Interactive mode and query mode are mutually exclusive")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# If the user didn't specify anything, print the help message
|
||||||
|
if not (args.interactive or args.query):
|
||||||
|
ap.print_help()
|
||||||
|
return 1
|
||||||
|
|
||||||
|
# Read the properties
|
||||||
|
commits = read_properties()
|
||||||
|
logger.debug(f"Read {len(commits)} commits")
|
||||||
|
|
||||||
|
# Open a connection to the database
|
||||||
|
if args.dump:
|
||||||
|
args.dump.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
args.dump.unlink(missing_ok=True)
|
||||||
|
conn = sqlite3.connect(args.dump if args.dump else ":memory:")
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Create a table to store the data
|
||||||
|
create_table(cursor)
|
||||||
|
|
||||||
|
# Insert the data into the table
|
||||||
|
rows = list(commits.items())
|
||||||
|
rows.sort(key=lambda x: x[1]["ct"])
|
||||||
|
for commit_hash, data in rows:
|
||||||
|
sql = "INSERT INTO commits VALUES (" + ",".join(["?"] * (len(FIELDS) + 1)) + ")"
|
||||||
|
values = [commit_hash] + [data.get(field, None) for field in FIELDS.keys()]
|
||||||
|
cursor.execute(sql, values)
|
||||||
|
|
||||||
|
# Commit the changes
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
# If just dumping, we are done
|
||||||
|
if args.dump:
|
||||||
|
conn.close()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# Dump to a temp file
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
temp_file = Path(tempfile.mkstemp()[1])
|
||||||
|
temp_conn = sqlite3.connect(temp_file)
|
||||||
|
temp_conn.executescript("\n".join(conn.iterdump()))
|
||||||
|
temp_conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
# Build the base sqlite command
|
||||||
|
sqlite_cmd = ["sqlite3", "--cmd", f".mode {args.mode}"]
|
||||||
|
if not args.no_header:
|
||||||
|
sqlite_cmd.append("--cmd")
|
||||||
|
sqlite_cmd.append(".headers on")
|
||||||
|
|
||||||
|
# If running a query, do so
|
||||||
|
if args.query:
|
||||||
|
subprocess.run(sqlite_cmd + [temp_file, args.query])
|
||||||
|
|
||||||
|
# If running interactively, do so
|
||||||
|
if args.interactive:
|
||||||
|
subprocess.run(sqlite_cmd + ["--interactive", temp_file])
|
||||||
|
|
||||||
|
# Delete the temp file
|
||||||
|
temp_file.unlink()
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
Loading…
x
Reference in New Issue
Block a user