Support Git repository and update it from upstream.
I don't remember what the --repositoryURL option was supposed to do, but instead I now assume that the it's a Git repository if you give --branchName and make a copy, and pull from upstream and reload when there are updates.
This commit is contained in:
		
							parent
							
								
									ce4c406fe6
								
							
						
					
					
						commit
						72559aa8d6
					
				
					 1 changed files with 96 additions and 23 deletions
				
			
		|  | @ -7,27 +7,34 @@ use strict; | |||
| use warnings; | ||||
| use autodie qw(:all); | ||||
| 
 | ||||
| use sigtrap 'handler' => \&CleanupEvertything, 'normal-signals', 'stack-trace' => 'error-signals'; | ||||
| 
 | ||||
| use Carp; | ||||
| 
 | ||||
| use Getopt::Long; | ||||
| use File::Spec::Functions; | ||||
| use File::Temp qw/:mktemp/; | ||||
| use File::Temp qw/:mktemp tempdir/; | ||||
| use Git::Repository 'Log'; | ||||
| 
 | ||||
| use POSIX qw(mkfifo); | ||||
| use IPC::Shareable; | ||||
| use Expect; | ||||
| 
 | ||||
| my $RSYNC_CMD = '/usr/bin/rsync'; | ||||
| 
 | ||||
| # We have to set the PAGER to a passthrough text program to assure that | ||||
| # output does not get paused | ||||
| $ENV{PAGER} = "/usr/bin/cat"; | ||||
| 
 | ||||
| my $BEANCOUNT_QUERY_CMD = "/usr/bin/bean-query"; | ||||
| 
 | ||||
| my($VERBOSE, $BEANCOUNT_DIR, $LOAD_FILE, $REPOSITORY_URL, $FIFO_DIR) = (0, undef, undef, undef, undef); | ||||
| my($VERBOSE, $BEANCOUNT_DIR, $LOAD_FILE, $BRANCH_NAME, $FIFO_DIR) = (0, undef, undef, undef, undef); | ||||
| 
 | ||||
| GetOptions("verbose=i" => \$VERBOSE, "beancountDir=s" => \$BEANCOUNT_DIR, | ||||
|            "loadFile=s" => \$LOAD_FILE, "repositoryURL=s" => \$REPOSITORY_URL, 'fifoDir=s' => \$FIFO_DIR); | ||||
|            "loadFile=s" => \$LOAD_FILE, "branchName=s" => \$BRANCH_NAME, 'fifoDir=s' => \$FIFO_DIR); | ||||
| 
 | ||||
| sub UsageAndExit($) { | ||||
|   print STDERR "usage: $0 --loadFile=/path/to/file.beancount --beancountDir=/path/to/beancountdir --fifoDir=/path/to/directory/for/fifos [ --repositoryURL=URL_OF_REPOSITORY --verbose=N ]\n"; | ||||
|   print STDERR "usage: $0 --loadFile=/path/to/file.beancount --beancountDir=/path/to/beancountdir --fifoDir=/path/to/directory/for/fifos [ --branchName=BRANCH_NAME --verbose=N ]\n"; | ||||
|   print STDERR "\n  $_[0]\n"; | ||||
|   exit 2; | ||||
| } | ||||
|  | @ -41,21 +48,60 @@ chdir $BEANCOUNT_DIR; | |||
| UsageAndExit("/path/to/file.beancount must a relative path to a file that exists in $BEANCOUNT_DIR") | ||||
|   unless (defined $LOAD_FILE and -r $LOAD_FILE); | ||||
| 
 | ||||
| if (defined $REPOSITORY_URL) { | ||||
|   UsageAndExit("if --repositoryURL is provided, $BEANCOUNT_DIR must be a checkout of a Git repository, but there is no $BEANCOUNT_DIR/.git/config.") | ||||
|   unless (-r '.git/config'); | ||||
| my($tempRepository, $tempRepositoryDirectory); | ||||
| 
 | ||||
|   open(my $gitFH, "<", ".git/config"); | ||||
|   my $repoString; | ||||
|   while (my $line = <$gitFH>) { | ||||
|     chomp $line; | ||||
|     $repoString = $1 | ||||
|       if $line =~ /^\s*url\s*=\s*(\S+)\s*$/; | ||||
| sub CleanupEvertything { | ||||
|   $tempRepository = undef if (defined $tempRepository); | ||||
|   $tempRepositoryDirectory = undef if (defined $tempRepositoryDirectory); | ||||
|   StopRunningBeanQuery(); | ||||
|   croak @_; | ||||
| } | ||||
| if (defined $BRANCH_NAME) { | ||||
|   my $absGitRepositoryDirectory = File::Spec->rel2abs( $BEANCOUNT_DIR ); | ||||
|   $tempRepositoryDirectory = tempdir('beancountquerygoofydaemongit_' . $$ . '_XXXXXXXXXXX', | ||||
|                                      TMPDIR => 1, CLEANUP => 1); | ||||
|   print STDERR "Copy Git repository to $tempRepositoryDirectory...." if $VERBOSE > 2; | ||||
|   system($RSYNC_CMD, '-Ha', "$absGitRepositoryDirectory/", "$tempRepositoryDirectory/"); | ||||
|   print STDERR "copy completed.\n" if $VERBOSE > 2; | ||||
|   $tempRepository = Git::Repository->new( work_tree => $tempRepositoryDirectory ); | ||||
| 
 | ||||
|   chdir $tempRepositoryDirectory; | ||||
|   $tempRepository->run(clean => '-fx', { quiet => 1 }); | ||||
|   $tempRepository->run(reset => '--hard', { quiet => 1 }); | ||||
|   $tempRepository->run(clean => '-fx', { quiet => 1 }); | ||||
|   $tempRepository->run(checkout => '$BRANCH_NAME', { quiet => 1 }); | ||||
| } | ||||
| 
 | ||||
| sub CheckUpstreamAndPull { | ||||
|   # Returns true iff. a pull was required and the files have changed. | ||||
|   return 0 unless (defined $tempRepository); | ||||
|   my $options = { quiet => 1 }; | ||||
|   if ($VERBOSE > 5) { | ||||
|     print STDERR "...clean & git pull..."; | ||||
|     $options = {}; | ||||
|   } | ||||
|   print STDERR "...check if upstream Git changed..." if $VERBOSE > 5; | ||||
|   my $updateOutput = $tempRepository->run(remote => 'update', $options); | ||||
|   print "$updateOutput" if defined $updateOutput and $updateOutput !~ /^\s*$/ and $VERBOSE > 5; | ||||
|   my $curRev = $tempRepository->run('rev-parse' => '@'); | ||||
|   my $remoteRev =  $tempRepository->run('rev-parse' => '@{u}'); | ||||
|   my $baseRev = $tempRepository->run('merge-base' => '@', '@{u}'); | ||||
|   print STDERR "...$curRev is current,  $remoteRev is remote Rev $baseRev is base...\n" if $VERBOSE > 6; | ||||
|   if ($curRev eq $remoteRev) { | ||||
|     print STDERR "no change..." if $VERBOSE > 5; | ||||
|     return 0; | ||||
|   } elsif ($curRev eq $baseRev) { | ||||
|     $tempRepository->run(clean => '-fx', $options); | ||||
|     $tempRepository->run(reset => '--hard', $options); | ||||
|     $tempRepository->run(clean => '-fx', $options); | ||||
|     my $pullOutput = $tempRepository->run('pull'); | ||||
|     print STDERR "\nPerformed pull since remote updated:\n  $pullOutput\n" if ($VERBOSE > 0); | ||||
|     return 1; | ||||
|   } else { | ||||
|     CleanupEvertything(); | ||||
|     die("our local Git has $curRev, upstream is at $remoteRev, and the base is $baseRev " . | ||||
|         "so give up entirely on trying to make this work."); | ||||
|   } | ||||
|   close $gitFH; | ||||
|   UsageAndExit("if --repositoryURL is provided, the checkout found in $BEANCOUNT_DIR must be of that repository, but .git/config does not list a URL.") unless defined $REPOSITORY_URL; | ||||
|   UsageAndExit("if --repositoryURL is provided, the checkout found in $BEANCOUNT_DIR must be of that repository, but it instead appears to be a checkout of $repoString.") | ||||
|     unless ($repoString eq $REPOSITORY_URL); | ||||
| } | ||||
| my $glue = 'BeAn'; | ||||
| my %options = ( | ||||
|  | @ -81,34 +127,61 @@ sub StartRunningBeanQuery { | |||
|   $format = $currentFormat unless defined $format; | ||||
|   $currentFormat = $format; | ||||
| 
 | ||||
|   if (defined $tempRepository) { | ||||
|     print STDERR "Clearing temp files from repository..." if $VERBOSE > 4; | ||||
|     $tempRepository->run(clean => '-fx', { quiet => 1 }); | ||||
|     $tempRepository->run(reset => '--hard', { quiet => 1 }); | ||||
|     $tempRepository->run(clean => '-fx', { quiet => 1 }); | ||||
|   } else { | ||||
|     my(@findCmd) = ("/usr/bin/find", '.', '-name', '*.picklecache'); | ||||
|     if ($VERBOSE > 4) { | ||||
|       print STDERR "Cleared the following picklecache files (none listed means none existed)...\n"; | ||||
|       push(@findCmd, '-ls'); | ||||
|     } | ||||
|     push(@findCmd, '-exec', '/usr/bin/rm', '-f', '{}', ';'); | ||||
|     system(@findCmd); | ||||
|     print STDERR "...done clearing picklecache files.\n" if ($VERBOSE > 4); | ||||
|   } | ||||
|   my @cmd = ($BEANCOUNT_QUERY_CMD); | ||||
|   push(@cmd, '-f', $format) if defined $format; | ||||
|   push(@cmd, $LOAD_FILE); | ||||
|     print STDERR "Starting beancount..." if $VERBOSE > 4; | ||||
|   $runningBeanQuery = Expect->spawn(@cmd); | ||||
|     print STDERR "...spawned & loading data..." if $VERBOSE > 4; | ||||
|   $runningBeanQuery->log_stdout(0); | ||||
|   $runningBeanQuery->expect(undef, -re => '^\s*beancount\s*\>\s*') | ||||
|     or die("Unable to find beancount prompt, output was instead: ". | ||||
|            $runningBeanQuery->before() . $runningBeanQuery->after()); | ||||
|   print STDERR "now ready." if $VERBOSE > 4; | ||||
|   print STDERR "Beancount started with output of:\n", $runningBeanQuery->before(), | ||||
|     $runningBeanQuery->match(), $runningBeanQuery->after(), "\n" | ||||
|     if ($VERBOSE > 3); | ||||
| } | ||||
| sub StopRunningBeanQuery { | ||||
|   return if not defined $runningBeanQuery; | ||||
|   $runningBeanQuery->send("exit\n"); | ||||
|   $runningBeanQuery->soft_close(); | ||||
| } | ||||
| CheckUpstreamAndPull(); | ||||
| StartRunningBeanQuery('text'); | ||||
| 
 | ||||
| print STDERR "Beancount started.  Main loop begins." if $VERBOSE > 0; | ||||
| while (1) { | ||||
|   if (not defined $query{question}) { | ||||
|     print STDERR "No question posed..." if $VERBOSE > 2; | ||||
|     print STDERR "No question posed..." if $VERBOSE > 5; | ||||
|     if (CheckUpstreamAndPull()) { | ||||
|       StopRunningBeanQuery(); | ||||
|       StartRunningBeanQuery(); | ||||
|     } | ||||
|     if (defined $query{fifoName}) { | ||||
|       print STDERR "fifo still active; locking to clear it..." if $VERBOSE > 2; | ||||
|       print STDERR "fifo still active; locking to clear it..." if $VERBOSE > 5; | ||||
|       (tied %query)->shlock; | ||||
|       print STDERR "clearing fifo, $query{fifoName}..." if $VERBOSE > 2; | ||||
|       print STDERR "clearing fifo, $query{fifoName}..." if $VERBOSE > 5; | ||||
|       no autodie 'unlink'; unlink($query{fifoName}); | ||||
|       %query = (); | ||||
|       (tied %query)->shunlock; | ||||
|       print STDERR "fifo cleared & lock released." if $VERBOSE > 2; | ||||
|       print STDERR "fifo cleared & lock released." if $VERBOSE > 5; | ||||
|     } | ||||
|     print STDERR "sleep for 2 seconds\n" if $VERBOSE > 2; | ||||
|     print STDERR "sleep for 2 seconds\n" if $VERBOSE > 5; | ||||
|     sleep 2; | ||||
|     next; | ||||
|   } elsif ($query{question} !~  /^[\,\=\~\-\@\w.\s\"\'\_\(\)\<\>\*\.\!]+$/) { | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Bradley M. Kuhn
						Bradley M. Kuhn