My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/development/tools/git-hyperpull/git-hyperpull.raku

91 lines
2.7 KiB

#!/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' ];
}