| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 | package SimplyGit::Git;use strict;use warnings;use Log::Log4perl qw(:easy);use lib ".";use SimplyGit::Shellex qw(shellex findBin);use Exporter qw(import);our @EXPORT_OK = qw(readConfig getStatus returnState addFiles commitChanges pushChanges stashAndReset resetFromUpstream updateGitIgnore appendRepoUserConfig parseSGConfig warnOnUser);# TODO: Add info/debug logging for all subroutinessub checkPath($$) {	my $path = shift;	my $logger = shift;	if ( ! -d $path ) {		$logger->error("$path doesn't look like a dir, exiting...");		exit 1;	}}sub warnOnUser($$$) {	my $user = shift;	my $email = shift;	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my $configuredUser = shellex("$gitCmd config --get user.name",$logger);	my $configuredEmail = shellex("$gitCmd config --get user.email",$logger);	if ( $configuredUser ne $user || $configuredEmail ne $email ) {		print "***************\n";		print "Your configured user/email don't match what you declared in the config file!\n";		print "Desired User: $user\nConfigured User: $configuredUser\nDesired Email: $email\nConfigured Email: $configuredEmail\n";		print "***************\n";	}}# https://perlmaven.com/trimsub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };sub parseSGConfig($$) {	my $config = shift;	my $logger = shift;	if ( ! -e $config ) {		$logger->error("$config doesn't look like a regular file, exiting...");		exit 1;	}	my $catCmd = findBin("cat",$logger);	my @configLines = split("\n",shellex("$catCmd $config",$logger));	my %configHash;	foreach my $line ( @configLines ) {		chomp $line;		if ( $line =~ m/^(.*)\ =\ "(.*)"$/ ) {			$configHash{$1} = $2;		}		if ( $line =~ m/^(.*)\ =\ \[(.*)\]/ ) {			my @trimmedPorts;			my @ports = split(",",$2);			foreach my $port (@ports) {				$port =~ /(\d{1,5})/;				push(@trimmedPorts,trim($1));			}			$configHash{$1} = \@trimmedPorts;		}	}	return %configHash;}sub returnConfigPath($$) {	my $path = shift;	my $logger = shift;	checkPath($path,$logger);	my $gitConfigPath = $path . "/" . ".git/config";	return $gitConfigPath;}	sub readConfig($$) {	# This sub is probably not really needed for what I'm trying to do	# git itself already parses this config...but an interesting exercise non the less	# and may be useful later	my $path = shift;	my $logger = shift;	my $gitConfigPath = returnConfigPath($path,$logger);	my $catCmd = findBin("cat",$logger);	my @configLines = split("\n",shellex("$catCmd $gitConfigPath",$logger));	# Key is config header, value is hash ref containing config values	my %gitConfig;	my @valueLines;	my $lineCounter = 0;	foreach my $line ( @configLines ) {		$lineCounter++;		#if ( $line =~ m/\[(.*)\]/ ) {		if ( $line =~ m/\[(.*)\]/ ) {			#$valueLine =~ /\t(.*)\ =\ (.*)$/;			$gitConfig{$1} = "";		}	}	# Tag each line with it's heading	# Only way I could think of that worked to solve how this	# There are almost certainly better ways	my @taggedLines;	my $tag = "NULLTAG";	foreach my $line ( @configLines ) {		if ( $line =~ m/\[(.*)\]/ ) {			$tag = $1;		} else {			my $newLine = $tag . $line;			push(@taggedLines,$newLine);		}	}	# Get all of the tagged lines into a hash structure.	foreach my $key ( keys %gitConfig ) {		my %stash;		foreach my $tl ( @taggedLines ) {			if ( $tl =~ m/^($key)/ ) {				$tl =~ s/^($key)//g;				$tl =~ m/^\t(.*)\ \=\ (.*)$/;				my $confKey = $1;				my $confVal = $2;				$stash{$confKey} = $confVal;			}		}		$gitConfig{$key} = \%stash;	}	return %gitConfig;}sub getStatus($) {	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my $status = shellex("$gitCmd status -uall --porcelain",$logger);	chomp $status;	return $status;}sub returnState($) {	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my $currentStatus = getStatus($logger);	my @statusLines = split("\n", $currentStatus);	my @untracked;	my @modified;	my @added;	my @deleted;	foreach my $file ( @statusLines ) {		$file =~ m/^\ {0,1}([A-Z?]{1,2})\ {1,2}(.*)/;		my $fileAttrs = $1;		my $filename = $2;		my @attrs = split("",$fileAttrs);		foreach my $attr ( @attrs ) {			if ( $attr =~ m/\?/ ) {				push(@untracked, $filename) unless grep $_ eq $filename, @untracked;			} 						if ( $attr =~ m/[M]/ ) {				push(@modified, $filename) unless grep $_ eq $filename, @modified;			} 						if ( $attr =~ m/[A]/ ) {				push(@added, $filename) unless grep $_ eq $filename, @added;			}			if ( $attr =~ m/[D]/ ) {				push(@deleted, $filename) unless grep $_ eq $filename, @deleted;			}		}	}	return ( \@untracked, \@modified, \@added, \@deleted );}sub addFiles($$) {	my $filesToAddRef = shift;	my $logger = shift;	my $gitCmd = findBin("git",$logger);	foreach my $file ( @$filesToAddRef ) {		shellex("$gitCmd add $file",$logger);	}}sub commitChanges($$) {	my $commitMsg = shift;	chomp $commitMsg;	my $logger = shift;	my $gitCmd = findBin("git",$logger);	shellex("$gitCmd commit -m \"$commitMsg\"",$logger);}sub pushChanges($) {	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my $output = shellex("$gitCmd push",$logger);}sub dropStash($) {	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my @stashList = split("\n", shellex("$gitCmd stash list",$logger));	my $stashCount = scalar @stashList;	# TODO: Don't need $stashCount, should just be able to iterate over @stashList	if ( scalar @stashList == 0 ) {		print "Stash is empty so not dropping\n";	} else {		foreach my $stashNum ( 1..$stashCount ) {			shellex("$gitCmd stash drop 0",$logger);		}	}}sub stashAndReset($) {	my $logger = shift;	my $gitCmd = findBin("git",$logger);	shellex("$gitCmd stash",$logger);	dropStash($logger);	shellex("$gitCmd rebase",$logger);}sub resetFromUpstream($) {	# git stash and git reset --hard and git pull ? I think	# git reset upstream/master; git stash	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my $upstream = shellex("$gitCmd config --get remote.upstream.url",$logger);	if ( $upstream eq "" || ! defined $upstream ) {		print "Upstream not configured, exiting\n";		exit 1;	}	shellex("$gitCmd reset upstream/master",$logger);	shellex("$gitCmd stash",$logger);	dropStash($logger);	print "Successful reset from upstream\n";	print "Changes have not been pushed, run \'$gitCmd pull\' to revert\n";}sub updateGitIgnore($$$) {	my $path = shift;	# Maybe better to accept an array of values	my $ignoreValue = shift;	my $logger = shift;	checkPath($path,$logger);	my $filename = $path . "/" . ".gitignore";	# Make sure we're not appending/writing if entry already exists in gitignore	if ( -f $filename ) {		my $catCmd = findBin("cat",$logger);		my @ignoreLines = split("\n",shellex("$catCmd $filename",$logger));		if ( ! grep( /^$ignoreValue$/, @ignoreLines ) ) {			open(my $fh, ">>", $filename) or die $logger->error("Couldn't open $filename, exiting...");			chomp $ignoreValue;			print $fh "$ignoreValue\n";			close $fh;		}	} else {		open(my $fh, ">", $filename) or die $logger->error("Couldn't open $filename, exiting...");		chomp $ignoreValue;		print $fh "$ignoreValue\n";		close $fh;	}}sub appendRepoUserConfig($$$) {	my $desiredName = shift;	my $desiredEmail = shift;	my $logger = shift;	my $gitCmd = findBin("git",$logger);	my $currentName = shellex("$gitCmd config --get user.name",$logger);	chomp $currentName;	my $currentEmail = shellex("$gitCmd config --get user.email",$logger);	chomp $currentEmail;	if ( $currentName eq $desiredName ) {		print "Already have $desiredName configured\n";	} else {		shellex("$gitCmd config user.name \"$desiredName\"",$logger);		print "Set $desiredName successfully\n";	}	if ( $currentEmail eq $desiredEmail ) {		print "Already have $desiredEmail configured\n";	} else {		shellex("$gitCmd config user.email \"$desiredEmail\"",$logger);		print "Set $desiredEmail successfully\n";	}}
 |