parent
2f62e3a718
commit
72a5277b1b
@ -0,0 +1 @@ |
|||||||
|
../../../licenses/GPL-3.0 |
@ -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 <file>..." 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. |
||||||
|
|
@ -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} <remote>:<path> |
||||||
|
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' ]; |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
with (import <nixpkgs> {}); |
||||||
|
(import <nom/raku.nix>).overrideAttrs ({ ... }: |
||||||
|
{ |
||||||
|
name = "git-hyperpull"; |
||||||
|
LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.libssh ]; |
||||||
|
}) |
Loading…
Reference in new issue