#!/usr/bin/perl -w # # p4_get for Safari # Copyright (c) 1999 by Barrie Slaymaker, rbs@telerama.com # # You may distribute under the terms of either the GNU General Public # License or the Artistic License, as specified in the README file. # # # Gets all files from a labelled version in to a subdirectory # # The subdirectory must be provided as the last argument, the # list of files to get is read from stdin or from a file named in ARGV. # The list of files should be the output of the 'p4 files' command. # use strict ; use Getopt::Long ; use File::Basename ; use File::Path ; use File::Copy ; my @options = ( 'rev|r=s', 'p4-file-list|l=s', 'out-file|o=s', ) ; my $options = {} ; GetOptions( $options, @options ) ; my $progname = basename( $0 ) ; die "no targets specified" unless @ARGV ; my $rev = $options->{'rev'} ; $rev = '_head' unless defined( $rev ) && length( $rev ) ; $rev = "_$rev" if $rev =~ /^(?:\d+|head)$/ ; $rev =~ s/^#/_/; my $out_file= $options->{'out-file'} ; $out_file = '' unless defined( $out_file ) && length( $out_file ) ; my $p4_file_list = $options->{'p4-file-list'} ; $p4_file_list = '' unless defined( $p4_file_list ) && length( $p4_file_list ) ; my $p4_files = get_p4_files() ; # print( join( "\n", map { $_->[0] . '#' . $_->[1] } @$p4_files ) ) ; # # Scan arg list, then find matching files. This makes the order # of the resulting fetches more expected than the other way. # while ( @ARGV ) { my $target = pop @ARGV ; $target =~ s@/\.\.\.$@@ ; $target =~ s@^//?@@ ; my $target_name_length = length( $target ) ; for ( @$p4_files ) { my $p4_name = $_->[0] ; my $p4_rev = $_->[1] ; die "undefined p4_name" unless defined $p4_name ; die "undefined file revision" unless defined $p4_rev ; my $file_rev = $p4_rev ; $file_rev =~ s/^#/_/ ; my $target_name = $p4_name ; $target_name =~ s@^//?@@ ; next unless substr( $target_name, 0, $target_name_length ) eq $target ; my $p4_rev_file_name = "$p4_name$p4_rev" ; my $rev_target_name = "$file_rev/$target_name" ; my $out_file_name = $out_file eq '' || $out_file eq '-' ? "$rev/$target_name" : $out_file ; get_file( $p4_rev_file_name, $rev_target_name ) ; if ( $rev_target_name ne $out_file_name ) { if ( -f $out_file_name ) { unlink $out_file_name or die "$: unlink $out_file_name" ; } else { my ( undef, $dir ) = fileparse( $out_file_name ) ; mkpath( $dir, 0, 0775 ) ; } link( $rev_target_name, $out_file_name ) or die "$!: link( $rev_target_name, $out_file_name )" ; # copy( $link, $out_file_name ) or # die "$!: copy( $link, $out_file_name )" ; # my @chunks = split( '/', $dir ) ; # my $updirs = '../' x @chunks ; # my $link = "$updirs$rev_target_name" ; # if ( ! -l $out_file_name || $link ne readlink $out_file_name ) { ## print $link, '<=>', readlink $out_file_name, "\n" ; # unlink( $out_file_name ) ; # mkpath( $dir, 0, 0775 ) # unless -d $dir ; # print( "$prog_name: Linking $out_file_name -> $rev_target_name\n" ) ; # symlink( $link, $out_file_name ) or # die "$!: symlink( $link, $out_file_name )" ; ## print $link, '<=>', readlink $out_file_name, "\n" ; # } } } } 0 ; ############################################################################## sub get_p4_files { my $file_list_name = $options->{'p4-file-list'} ; my ( undef, $file_dir ) = fileparse( $file_list_name ) ; mkpath( $file_dir, 0, 0775 ) unless -d $file_dir ; my $p4 ; if ( defined $file_list_name && -f $file_list_name ) { $p4 = $file_list_name ; open( P4, "<$p4" ) or die "$!: $p4" ; } else { # Clean up the rev since "#" is passed in as an underscore my $p4_rev = $rev ; $p4_rev =~ s/^_/#/ ; $p4 = "p4 files //...$p4_rev" ; print( "Getting '$p4' list\n" ) ; open( P4, "$p4 |" ) or die "$!: p4 files command" ; } my $p4_files = [] ; my $none_such ; while ( <P4> ) { chomp ; my ( $name, $rev, $action, $desc ) = /^([^#]+)(#\d+)\s+-\s+(\w+)\s+(.*)/ ; next unless defined $desc && $action ne 'delete' ; push( @$p4_files, [ $name, $rev, $action, $desc ] ) ; } die "$!: $p4" unless close( P4 ) ; return $p4_files ; } ################################ sub get_file { my ( $p4_name, $file_name ) = @_ ; if ( -f $file_name ) { # print( "$progname: $file_name exists\n" ) ; return } my ( undef, $dir ) = fileparse( $file_name ) ; mkpath( $dir, 0, 0775 ) unless -d $dir ; open( OUTPUT, ">$file_name" ) or die "$! opening $file_name" ; my $p4 = "p4 print $p4_name |" ; print( "$progname: $file_name\n" ) ; # print( '.' ) ; open( P4, $p4 ) or die "$!: $p4" ; my $first_line = <P4> ; # print $first_line ; $\ = undef ; while (<P4>) { print OUTPUT $_ or die "$!" ; } unless ( close( OUTPUT ) ) { my $msg = $! ; print "$progname: unlinking $file_name\n" ; unlink( $file_name ) or print STDERR "$progname: $! unlinking $file_name\n" ; die "$msg closing $file_name" ; } unless( close( P4 ) ) { my $code = $? ; print "$progname: unlinking $file_name\n" ; unlink( $file_name ) or print STDERR "$progname: $! unlinking $file_name\n" ; die "$p4 returned $code" ; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 202 | Barrie Slaymaker |
Converted to use hard links instead of symlinks or copies when making @something/...... from _1/...... in the interests of saving disk space and of allowing tar to archive something other than a bunch of symlinks when taring up a directory. |
||
#4 | 178 | Barrie Slaymaker |
Modified cgimake to get the project name out of the target name if one isn't supplied. This makes it so that Apache's mod_rewrite is no longer needed to extract the project name from the URL and place it in the QUERY_STRING, and so that you can call cgimake from the command line and place the project name in the target path: cgimake /perl/_head/Default/depot/ Modified cgimake to work easily from the command line Fixed some minor bugs in assembling paths that were causing // to appear in paths when no project is specified. Fixed minor bug that cause cgimake to try to read a bogus config file when there is no $project Tweaked p4_get to provide a more reasonable level of verbosity. Updated the apache doc to reflect the simpler, non-rewrite technique. Added targets to fetch a new _head revision if the head change number has changed. Need to check in p4_update. |
||
#3 | 168 | Barrie Slaymaker | Added YAPC paper, slides | ||
#2 | 165 | Barrie Slaymaker | Applied Greg KH's license patch. | ||
#1 | 162 | Barrie Slaymaker | First code & documentation checkin |