From 72a5277b1b60c2a2a41da39417dcbc32d42340d5 Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Wed, 10 Mar 2021 18:38:57 +0100 Subject: [PATCH] git-hyperpull: initial code dump --- development/tools/git-hyperpull/.projectile | 0 development/tools/git-hyperpull/LICENSE | 1 + development/tools/git-hyperpull/README.md | 42 +++++++++ .../tools/git-hyperpull/git-hyperpull.raku | 91 +++++++++++++++++++ development/tools/git-hyperpull/shell.nix | 6 ++ 5 files changed, 140 insertions(+) create mode 100644 development/tools/git-hyperpull/.projectile create mode 120000 development/tools/git-hyperpull/LICENSE create mode 100644 development/tools/git-hyperpull/README.md create mode 100755 development/tools/git-hyperpull/git-hyperpull.raku create mode 100644 development/tools/git-hyperpull/shell.nix diff --git a/development/tools/git-hyperpull/.projectile b/development/tools/git-hyperpull/.projectile new file mode 100644 index 00000000000..e69de29bb2d diff --git a/development/tools/git-hyperpull/LICENSE b/development/tools/git-hyperpull/LICENSE new file mode 120000 index 00000000000..f837ab4da5f --- /dev/null +++ b/development/tools/git-hyperpull/LICENSE @@ -0,0 +1 @@ +../../../licenses/GPL-3.0 \ No newline at end of file diff --git a/development/tools/git-hyperpull/README.md b/development/tools/git-hyperpull/README.md new file mode 100644 index 00000000000..029fe98f2e4 --- /dev/null +++ b/development/tools/git-hyperpull/README.md @@ -0,0 +1,42 @@ +# git-hyperpull + +Pull uncommited changes from a remote copy of this repository into your index. + +## How to use + +To run git-hyperpull you need to be in the root of your repository. +Under the hood, git-hyperpull simply runs `ssh ...` commands, so you +can rely on alias entries in your ssh config file. + +```console +$ git hyperpull myremote:~/myproject +Prepare environment... +Generating patch... +Pulling patch... +0001-generated-by-git-hyperpull.patch 100% 40KB 450.9KB/s 00:00 +Applying patch... +Deleting patch... +Cleaning up remote... + +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +Changes to be committed: + (use "git restore --staged ..." to unstage) + new file: development/tools/git-hyperpull/.projectile + new file: development/tools/git-hyperpull/git-hyperpull.raku + new file: development/tools/git-hyperpull/shell.nix +``` + +## How to install + +TBD + + +## License + +`git-hyperpull` is free software, licensed under the GNU General +Public License 3.0 (or later). See the LICENSE file for a full copy +of the license. + diff --git a/development/tools/git-hyperpull/git-hyperpull.raku b/development/tools/git-hyperpull/git-hyperpull.raku new file mode 100755 index 00000000000..e3f6776b8b4 --- /dev/null +++ b/development/tools/git-hyperpull/git-hyperpull.raku @@ -0,0 +1,91 @@ +#!/usr/bin/env raku + +sub USAGE() { + print Q:c:to/EOH/; +Pull uncommited changes from a remote copy of this repository into your index. + +Usage: + {$*PROGRAM-NAME} : +EOH +} + +## Run a command on a remote and hide stderr from the user +sub cmd_on_remote($remote, $path, @cmd) returns Int { + my $p = run 'ssh', "$remote", "cd $path; $(@cmd)", :out, :err; + $p.out.slurp: :close; # Consume stdout nom nom nom + $p.err.slurp: :close; # Consume stderr nom nom nom + $p.exitcode +} + +## Prepare the environment by cleaning up .git/hypergit +sub prepare_env($remote, $path) { + say 'Prepare environment...'; + + my $dirty = cmd_on_remote($remote, $path, [ 'stat', '.git/hyperpull' ]); + + if $dirty { + say 'Cleaning up previous .git/hyperpull state directory...'; + cmd_on_remote($remote, $path, [ 'rm', '-rf', '.git/hyperpull' ]); + } +} + + +## Generate a patch and store +sub generate_patch($remote, $path) { + say 'Generating patch...'; + + cmd_on_remote $remote, $path, [ 'git', 'add', '-A' ]; + cmd_on_remote $remote, $path, [ 'git', 'commit', '-m', "'generated by git-hyperpull'" ]; + cmd_on_remote $remote, $path, [ 'git', 'format-patch', 'HEAD~', '-o', '.git/hyperpull' ]; + cmd_on_remote $remote, $path, [ 'git', 'reset', 'HEAD^' ]; +} + +## Pull the generated patch files +sub pull_patch($remote, $path) { + say 'Pulling patch...'; + my $p = run 'scp', + "$remote:$path/.git/hyperpull/0001-generated-by-git-hyperpull.patch", + '.', + :err; + $p.err.slurp: :close; # Consume stderr nom nom nom +} + +## Check that we are in the root of the repository +sub check_directory { + my $p = run 'stat', '.git', :out, :err; + $p.out.slurp: :close; + $p.err.slurp: :close; + if $p.exitcode { + say 'You must run git-hyperpull from the repository root!'; + exit 1; + } +} + +## Main function hook that runs when the user provides enough parameters +sub MAIN($remote_path) { + check_directory(); + + # Split argument along the : - hopefully some shells can auto-complete this easier + my ($host, $path) = split(":", $remote_path); + + # Make sure we have a clean .git/hyperpull directory to work with + prepare_env $host, $path; + + # Generate the remote patch + generate_patch $host, $path; + + # Pull and apply patch locally + pull_patch $host, $path; + + # Apply local patch + say 'Applying patch...'; + run 'git', 'apply', '-3', '--index', '--intent-to-add', './0001-generated-by-git-hyperpull.patch'; + + # Delete local patch + say 'Deleting patch...'; + run 'rm', './0001-generated-by-git-hyperpull.patch'; + + # Clean up remote .git/hyperpull directory + say 'Cleaning up remote...'; + cmd_on_remote $host, $path, [ 'rm', '-rf', '.git/hyperpull' ]; +} diff --git a/development/tools/git-hyperpull/shell.nix b/development/tools/git-hyperpull/shell.nix new file mode 100644 index 00000000000..fc910426b13 --- /dev/null +++ b/development/tools/git-hyperpull/shell.nix @@ -0,0 +1,6 @@ +with (import {}); +(import ).overrideAttrs ({ ... }: + { + name = "git-hyperpull"; + LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.libssh ]; + })