Introduction
Most people will tell you git is a source control tool; some people will tell you that git is a content-addressable filesystem. It's all that, but the interesting thing is that it's a single-tool interface to frameworks that allow you to create products as a team.
Enter the absolutely simple extension mechanism that git has: write a n executable called git-xxx and git
will dutifully call it when you make git xxx. Which is why, to make an easier onramp for students in my 7th-semester class in Computer Science, I created an extension called git iv
(IV is the acronym for the class). The extension allows them to create branches with specific names, as well as upload those branches, without needing to remember specific git
commands.
You might argue that remembering
git
commands is what students should do, but in fact they don't, and since this is not part of the core of the class, I prefer to eliminate sources of trouble for them (which eventually become sources of trouble for me) using this.
Writing the extension in Perl
There are many good things that can be said about Perl, for this or for anything else. But in this case there's a thing that makes it ideal for writing extensions: git
includes a Perl module called Git
, which is a Perl interface to all the Git commands. This is distributed with git
, so if you've got git
, you've got this library.
The whole extension is not hosted in this GitHub repo; this will contain the most up-to-date version as well as documentation and other stuff.
So here's the preamble to the extension:
use strict;
use warnings;
use lib qw( /Library/Developer/CommandLineTools/usr/share/git-core/perl
/usr/share/perl5 );
use Git;
use v5.14;
my $HELP_FLAG = "-h";
my $USAGE_STRING = <<EOC;
Uso:
git iv objetivo <número> -- crea una rama para ese objetivo
git iv sube-objetivo -- sube al repo remoto la rama
git iv $HELP_FLAG -- imprime este mensaje
EOC
The main caveat about the extension is that some flags will be handled by git
itself. There are probably quite a few of those, but one of them is --help
. git xxx --help
will try to look up a manual page for git xxx
. This is why above a different help flag is defined. And also a usage string, which is helpful when you don't remember the exact shape of the subcommands. In this case, I use git iv
as the extension name and as interface to the stuff that needs to be made; but there are subcommands that will do different things. These are implemented later:
my @subcommands = qw(objetivo sube-objetivo);
push( @subcommands, quotemeta $HELP_FLAG);
die( usage_string() ) unless @ARGV;
my $subcommand = shift;
die "No se reconoce el subcomando $subcommand" unless grep( /\Q$subcommand/, @subcommands );
my @args = @ARGV;
I prefer not to include any dependencies; there are powerful command line flag libraries out there, but in this case, a single script is best. So you handle whatever comes after iv
uniformly, be it a subcommand or a flag. But the issue with the flag is that it includes a dash -
, so we wrap it so that it can be used safely in regexes. Like the one, for instance, 4 lines below: in case the subcommand at the front of the command line is not part of the list, it will bail out showing the usage string.
Anything after the subcommand will be gobbled into @args
.
if ( $subcommand eq $HELP_FLAG ) {
say $USAGE_STRING;
} else {
my $repo;
eval {
$repo = Git->repository;
} or die "Aparentemente, no estás en un repositorio";
if ( $subcommand eq "objetivo" ) {
die $USAGE_STRING unless @args;
$repo->command( "checkout", "-b", "Objetivo-" . $args[0]);
}
if ( $subcommand eq "sube-objetivo" ) {
my $branch = $repo->command( "rev-parse", "--abbrev-ref", "HEAD" );
chomp($branch);
$repo->command ( "push", "-u", "origin", $branch );
}
}
Now it's a matter of processing the subcommand. If it's the flag -h
, print the usage string; if it's any of the other subcommands, we need to work with the git repository.
$repo = Git->repository;
creates an object out of the Git
library we mentioned before that we will use to issue the different plumbing or high level commands. One of the subcommands will do a checkout: $repo->command( "checkout", "-b", "Objetivo-" . $args[0]);
will convert itself to the equivalent command. You can even work with plumbing commands such as rev-parse
to check the branch you're in and create that branch remotely, ad the other command does.
Concluding
Perl saves you a whole lot of trouble when writing this kind of thing. Besides, the fact that it will be most probably be installed in any system you use to develop (Mac, Linux or WSL) will save you trouble asking for prerequisites for this script.
Top comments (0)