#!/usr/bin/perl # # gchk This script creates a new git branch with a given name # and an updated index number. # # The name conventions is: # # component.NNNNNN # # component - a name provided by the user # NNNNNN - an index number calculated by previous branch # names using this component (if any) # # usage: # gchk [options] # # Revision History # 1.0 Initial revision. 140107 # 1.1 Added license info. 180616 # # Written by Wayne Morrison, 140107. # # Copyright 2014 Wayne Morrison # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; use Getopt::Long qw(:config no_ignore_case_always); # # Version information. # my $NAME = "gchk"; my $VERS = "$NAME version: 1.1"; ############################################################################ # # Options fields. # my %opts = (); # Options. # # Command line arguments. # my @opts = ( 'last', # Check out a component's last branch. 'show', # Show a component's branches. 'verbose', # Give verbose output. 'help', # Give a help message. 'Version', # Display the program version. ); my $last = 0; my $show = 0; my $verbose = 0; ############################################################################ my %branchlist = (); # List of the name's branches. $| = 1; main(); exit(0); #----------------------------------------------------------------------------- # Routine: main() # # Purpose: Do the work -- parse args, get the final branch index, and # run the appropriate command. # sub main { my $component; # Name of component for new branch. my $brind; # New branch's index. # # Munch on the options and arguments. # $component = optsandargs(); # # Get the index number for the new branch. # $brind = branchindex($component); printf("last branch: $component.%06d\n",$brind) if($verbose && !$show); # # Do our Big Thing now. # if($last) { # # Build the new branch name. # Enter the name's last branch. # $brind = int($brind); brancher($component,$brind,''); } elsif($show) { my $len = length($component) + 6; # Length of branch names. # # List the name's branches. # foreach my $br (sort(keys(%branchlist))) { if($verbose) { printf("%*s $branchlist{$br}\n",$len,$br); } else { print "$br\n"; } } } else { # # Get the new branch index and create the new branch. # $brind = int($brind) + 1; brancher($component,$brind,'-b'); } } #---------------------------------------------------------------------- # Routine: optsandargs() # # Purpose: Parse the command line for options and arguments. # sub optsandargs { # # Parse the options. # GetOptions(\%opts,@opts) || usage(); # # Check for some immediate-action options. # usage() if(defined($opts{'help'})); version() if(defined($opts{'Version'})); # # Now set some flags. # $last = $opts{'last'}; $show = $opts{'show'}; $verbose = $opts{'verbose'}; # # Check for option and argument validity. # usage() if($last && $show); usage() if(@ARGV != 1); # # Return the first argument as the component. # return($ARGV[0]); } #---------------------------------------------------------------------- # Routine: branchindex() # # Purpose: stuff to do. # sub branchindex { my $component = shift; # Component to find. my @branches = (); # List of component's branches. # # Get a list of our git branches. # open(BRANCHES,"git branch -v|"); # # Look through the branches to find the current branch and a # list of this component's branches. # while() { my $line; # A branch name. # # Get the line, dump the newline. # $line = $_; chomp $line; # # Ensure the current branch is the master. # The exception is that we can -show while not in master. # if($line =~ /^\*/) { $line =~ /^\* (\S+) /; if(($1 ne 'master') && (! $show)) { print "current branch - <$line>\n"; print STDERR "gchk must be run while \"master\" is the current branch.\n"; exit(1); } } # # If this is one of our component's branches, we'll # save the branch's index and name. # if($line =~ /^ ($component\.(\d+)) +[0-9a-f]+ (.*)$/) { push @branches, $2; $branchlist{$1} = $3; } } # # Let git rest. # close(BRANCHES); # # Sort the branch indices. # (Probably unnecessary, but we'll still do it.) # @branches = sort @branches; # # Return the largest branch index. # return($branches[-1]); } #----------------------------------------------------------------------------- # Routine: brancher() # # Purpose: Run the necessary git command. # sub brancher { my $name = shift; # Branch's base name. my $brind = shift; # Branch index. my $cmdarg = shift; # Argument for "git branch". my $brname; # Branch name. # # Build the branch name. # $brname = sprintf("$name.%06d", $brind); printf("branch name: $name.%06d\n",$brind); # # Enter the branch, maybe creating it along the way. # print "(git checkout $cmdarg $brname)\n" if($verbose); exec "git checkout $cmdarg $brname"; exit($? >> 8); } #---------------------------------------------------------------------- # Routine: version() # # Purpose: Print the version number(s) and exit. # sub version { print STDERR "$VERS\n"; exit(0); } #---------------------------------------------------------------------- # Routine: usage() # # Purpose: Give usage message and exit. # sub usage { print STDERR "usage: gchk [options] \n"; print STDERR "\n"; print STDERR "\twhere [options] are:\n"; print STDERR "\t\t-last\n"; print STDERR "\t\t-show\n"; print STDERR "\t\t-verbose\n"; print STDERR "\t\t-help\n"; print STDERR "\t\t-Version\n"; exit(0); } 1; ############################################################################## =pod =head1 NAME B - create a new B branch for a given component =head1 SYNOPSIS gchk [options] =head1 DESCRIPTION B creates a new B branch with a given name and an updated index number. Branch names follow a standard naming format that specifies a name and an index number is appended to the name. When creating a new branch, the current branch must be "master". The branch names follow this format: name.NNNNNN The "name" portion is specified by the user and the "NNNNNN" index number is calculated by B. B is given the name and it determines the index number to use. If this is the first branch to use this name, then the index number will be "000001". Otherwise, the last index will be incremented and that number will be used. The numbers are six digits long, with leading zeroes included. This makes it easier to sort the branch names. The I<-last> and I<-show> options, described below, do not create new branches. They are used to assist in working with branches named in the aforementioned format. The B command may be used to easily merge branches named in this format with the "master" branch. B and B do not use meaningful branch names and they should not be used if meaningful branch names are required. These commands are useful in situations where there are many files being managed by B, frequent changes are being made to those files, and creating meaningful branch names is likely to become time-consuming and a hindrance. =head1 OPTIONS B takes the following options: =over 4 =item I<-last> This option checks out the last existing branch for a given name. When using this option, the current branch must be "master". This option is mutually exclusive from I<-show>. =item I<-show> This option lists the branches for a given name. If this option is given with the I<-verbose> option, then each branch's informational message will be given along with the name. Otherwise, only the branch names will be listed. This option is mutually exclusive from I<-last>. =item I<-verbose> This option provides verbose information about B's operation. =item I<-Version> Display the version information for B. =item I<-help> Display a help message. =back =head1 LICENSE Copyright 2014 Wayne Morrison Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =head1 AUTHOR Wayne Morrison, wayne@waynemorrison.com =head1 SEE ALSO B, B =cut