package VCP::Dest::svn ; =head1 NAME VCP::Dest::svn - svn destination driver (Not Supported or Ready For Production) =head1 SYNOPSIS vcp <source> svn:<repo_uri>:<dest_dir> vcp <source> svn:file:///path/to/repo:/path/to/dir --create-repo where <repo_uri> is any URI to a repository root that you'd pass to the svn command and <dest_dir> is the directory or file within that location. =head1 DESCRIPTION STATUS: alpha. This is just good enough to use in VCP's own test suite. This driver allows L<vcp|vcp> to insert revisions in to a SVN repository. If the file:/// repository does not exist and the --create-repo option is passed, it is created with "svnadmin create". If <dest_dir> does not exist it is created with "svn mkdir" See L<VCP::Filter::map|VCP::Filter::map>'s <<branch_to(...)>> action for a tool that lets you map labels (a.k.a. tags) to svn tag branches via svn copy. =head1 OPTIONS =over =item --create-repo Initializes a svn repository in the directory indicated in the svn URL spec (which must be a scheme supported by svnadmin). Refuses to init a non-empty directory. =item --delete-repo If C<--create> is passed and the target directory is not empty, it will be deleted. THIS IS DANGEROUS AND SHOULD ONLY BE USED IN TEST ENVIRONMENTS. =back =cut $VERSION = 1 ; @ISA = qw( VCP::Dest VCP::Utils::svn ); use strict ; use Carp ; use File::Basename ; use File::Path ; use VCP::Debug qw( :debug ); use VCP::Dest; use VCP::Logger qw( pr lg pr_doing ); use VCP::RefCountedFile; use VCP::Rev ; use VCP::Utils qw( empty is_win32 ); use VCP::Utils::svn qw( RCS_underscorify_tag ); sub new { my $self = shift->SUPER::new( @_ ) ; ## Parse the options my ( $spec, $options ) = @_ ; $self->parse_svn_repo_spec( $spec ) unless empty $spec; $self->parse_options( $options ); return $self ; } sub options_spec { my $self = shift; return ( $self->SUPER::options_spec, "create-repo" => \$self->{SVN_CREATE_REPO}, "delete-repo" => \$self->{SVN_DELETE_REPO}, ); } sub sort_filters { require VCP::Filter::stringedit; return ( shift->require_change_id_sort( @_ ), VCP::Filter::stringedit->new( ## A catch-all to prevent illegal file names. This might ## result in filename collisions, but it's probably very much ## good enough for 99.9% of the cases. ## ## The pattern => replacement scheme was suggested by Marc Tooley. ## ## TODO: implement detection and correction of collisions as ## a separate filter. "", [ "user_id,name", "*", "_star_" , "user_id,name", "?", "_quest_" , "user_id,name", "\@", "_at_" , ], ), ); } sub init { my $self = shift; ## Set default repo_id. $self->repo_id( "svn:" . $self->repo_server ) if empty $self->repo_id && ! empty $self->repo_server ; $self->repo_filespec( $self->repo_filespec . "/..." ) if $self->repo_filespec =~ m{\A[^/\\]+\z}; $self->deduce_rev_root( $self->repo_filespec ) ; if ( $self->{SVN_CREATE_REPO} ) { if ( $self->{SVN_DELETE_REPO} ) { $self->rev_map->delete_db; $self->head_revs->delete_db; $self->files->delete_db; } $self->create_repo; } else { pr "ignoring --delete-repo, which is only useful with --init-repo" if $self->{SVN_DELETE_REPO}; } $self->rev_map->open_db; $self->head_revs->open_db; $self->files->open_db; # $self->command_stderr_filter( # qr{^(?:svn (?:server|add|remove): (re-adding|use 'svn commit' to).*)\n} # ) ; } sub create_repo { my $self = shift; my $root = $self->repo_server; die "svn URI undefined\n" unless defined $root; die "svn URI is empty string\n" if $root eq ""; die "svn URI must be a \"file:\" URI: \"$root\"\n" unless ( my $path = $root ) =~ s{^file://}{}i; die "$path is not a dir\n" if -e $path && ! -d _; my @files; @files = glob "$path/*" if -d $path; if ( @files && $self->{SVN_DELETE_REPO} ) { require File::Path; rmtree [ @files ]; @files = glob "$path/*"; } die "cannot svnadmin create non-empty dir $path\n" if @files; $self->svnadmin( [ qw( create ), $path ] ); } sub handle_header { my $self = shift ; my ( $h ) = @_; if ( empty( $self->repo_filespec ) || $self->repo_filespec =~ m{^/*\.\.\.\z} ) { my $filespec = $h->{rev_root}; die "vcp: no SVN destination module selected and source rev_root is \"\"\n" if empty $filespec; $self->repo_filespec( $filespec ); $filespec .= "/..."; $self->deduce_rev_root( $self->repo_filespec ); } $self->create_svn_workspace( create_in_repository => 1, ) ; $self->{SVN_PENDING_DIRS} = [] ; $self->{SVN_PENDING} = [] ; $self->{SVN_PREV_CHANGE_ID} = undef ; $self->{SVN_LAST_MOD_TIME} = {} ; $self->SUPER::handle_header( @_ ) ; } sub checkout_file { my $self = shift ; my $r ; ( $r ) = @_ ; lg "$r checking out ", $r->as_string, " from svn dest repo"; my $fn = $r->name; $fn =~ s{^[\\/]+}{}; my $work_path = $self->work_path( $fn ) ; debug "work_path '$work_path'" if debugging; my ( undef, $work_dir ) = fileparse( $work_path ) ; $self->mkpdir( $work_path ) unless -d $work_dir ; my $rev_id = ($self->rev_map->get( [ $r->source_repo_id, $r->id ] ))[1]; $self->svn( [ "update", -r => $rev_id, $fn ], \undef, ) ; die "'$work_path' not created by svn checkout" unless -e $work_path ; return $work_path; } sub handle_rev { my $self = shift ; my ( $r ) = @_; debug "got ", $r->as_string if debugging; my $change_id = $r->change_id; $self->commit( "end of change $self->{SVN_PREV_CHANGE_ID} reached" ) if @{$self->{SVN_PENDING}} && $change_id ne $self->{SVN_PREV_CHANGE_ID}; $self->{SVN_PREV_CHANGE_ID} = $change_id ; my $fn = $r->name; ## No need to denormalize; the svn workspace is mapped ## to the appropriate place. $fn =~ s{\A[\\\/]+}{}; debug $fn if debugging; my $svn_path = $self->repo_filespec . "/" . $fn; my $work_path = $self->work_path( $fn ) ; if ( $r->is_base_rev ) { $self->compare_base_revs( $r, $work_path ) if defined $work_path ; pr_doing; return; } if ( $r->action eq 'delete' ) { # $self->commit( "time to do a delete" ) if @{$self->{SVN_PENDING}}; unlink $work_path || die "$! unlinking $work_path" ; $self->svn( ["remove", $fn] ) ; ## Do this commit by hand since there are no SVN_PENDING revs, which ## means $self->commit will not work. It's relatively fast, too. push @{$self->{SVN_PENDING}}, $r; $self->files->set( [ $svn_path ], "deleted" ); pr_doing; } else { ## TODO: Move this in to commit(). { my ( undef, $rel_work_dir, undef ) = File::Spec->splitpath( $fn ) ; my @dirs = File::Spec->splitdir( $rel_work_dir ); my @cur_dirs; shift @dirs while @dirs && !length $dirs[0]; while ( @dirs ) { push @cur_dirs, shift @dirs; my $cur_path = $self->work_path( @cur_dirs ); next if -e $cur_path; my $rel_cur_path = join "/", @cur_dirs; lg "\$ mkdir $rel_cur_path"; mkpath [ $cur_path ], 0, 0770; lg "\$ svn add $rel_cur_path"; $self->svn( ["add", $rel_cur_path ] ); push @{$self->{SVN_PENDING_DIRS}}, $rel_cur_path; } } my $branch_id = $r->branch_id; $branch_id = "" unless defined $branch_id; ## See if this should be the main branch for this file. if ( $r->is_placeholder_rev ) { if ( $r->is_branch_rev ) { ## Note: this ignores clones of branch revs. my $branch_tag = RCS_underscorify_tag $branch_id; my $from_id = $r->from_id; $from_id = $r->previous_id if empty $from_id; my ( $psvn_name, $prev_id ) = $self->rev_map->get( [ $r->source_repo_id, $from_id ] ); # create the new branch. my $repo_spec = $self->repo_server; $self->svn( [ "copy", "$repo_spec/$psvn_name", "-r" . $prev_id, $fn ] ); $self->files->set( [ $svn_path ], "branched" ); push @{$self->{SVN_PENDING}}, $r; } pr_doing; return; } ## TODO: Don't assume same filesystem or working link(). ## TODO: Batch these. $self->{SVN_FILES}->{$r->id} = VCP::RefCountedFile->new( $work_path ) ; my $source_fn = $r->get_source_file; if ( $source_fn ne $work_path ) { debug "linking $source_fn to $work_path" if debugging; unlink $work_path if -e $work_path; link $source_fn, $work_path or die "$! linking '$source_fn' -> '$work_path'" ; } if ( defined $r->mod_time ) { utime $r->mod_time, $r->mod_time, $work_path or die "$! changing times on $work_path" ; } my ( $acc_time, $mod_time ) = (stat( $work_path ))[8,9] ; while ( ( $self->{SVN_LAST_MOD_TIME}->{$work_path} || 0 ) == $mod_time ) { lg "tweaking mod_time on '$work_path' from ", "".localtime $mod_time, " to ", "".localtime $mod_time + 1, " at ", "".localtime; ++$mod_time ; utime $acc_time, $mod_time, $work_path or die "$! changing times on $work_path" ; } $self->{SVN_LAST_MOD_TIME}->{$work_path} = $mod_time ; my @file_state = $self->files->get( [ $svn_path ] ); unless ( @file_state && $file_state[0] ne "deleted" ) { ## New file. $self->svn( [ "add", $fn ] ) ; $self->files->set( [ $svn_path ], "added" ); } else { ## Change the existing file (no need to tell svn this) } push @{$self->{SVN_PENDING}}, $r ; } } sub handle_footer { my $self = shift ; $self->commit( "end of transfer" ) if $self->{SVN_PENDING} && @{$self->{SVN_PENDING}} ;#|| $self->{SVN_DELETES_PENDING} ; delete $self->{SVN_FILES}; $self->SUPER::handle_footer ; } sub comment_option { ## Packages the comment in an acceptable form on Win32 or Unix. ## returns the appropriate svn command line options. my $self = shift; my $comment = shift; return ( "-m", "" ) if empty $comment; return ( "-m", $comment ) unless is_win32; ## Win32 shell must be avoided at all costs. my $cfn = $self->work_path( "comment.txt" ) ; open COMMENT, ">$cfn" or die "$!: $cfn"; print COMMENT $comment or die "$!: $cfn"; close COMMENT or die "$!: $cfn"; return ( "-F$cfn" ); } sub commit { my $self = shift ; lg "committing: ", @_; return unless @{$self->{SVN_PENDING}} ; ## All comments should be the same, since we alway commit when the ## comment changes. my $comment = do { my %seen_comments; join "", map ! length $_ || substr( $_, -1 ) eq "\n" ? $_ : "$_\n", grep !$seen_comments{$_}++, map $_->comment, @{$self->{SVN_PENDING}}; }; my $commit_log; $self->svn( ["commit", $self->comment_option( $comment ) ], undef, \$commit_log ); lg $commit_log if $commit_log =~ /\S/; my ( $svn_rev_id ) = $commit_log =~ /Committed revision (\d+)/ or die "No \"Committed revision\" string found in:\n", $commit_log; for my $r ( @{$self->{SVN_PENDING}} ) { my $name = $r->name; $name =~ s{^[\\/]+}{}; $self->rev_map->set( [ $r->source_repo_id, $r->id ], $self->repo_filespec . "/" . $name, $svn_rev_id ); $self->head_revs->set( [ $r->source_repo_id, $r->source_filebranch_id ], $r->source_rev_id, $r->action ); } $commit_log = undef; ## Allow Perl GC and $r->DESTROY to clean up the filesystem and ## throw away the source file. for my $r ( @{$self->{SVN_PENDING}} ) { pr_doing; } @{$self->{SVN_PENDING}} = () ; @{$self->{SVN_PENDING_DIRS}} = (); } =head1 LIMITATIONS Does not handle "clone" revisions properly. "clone" revisions are generated by L<VCP::Source::svn|VCP::Source::svn> when a branch is given two branch tags. See L<VCP::Source::svn|VCP::Source::svn> for more details. Does not guarantee that the source repository's mod_time will be applied because subversion seems to assume that, if the size and mod_time have not changed, the file has not changed. So this driver bumps the mod_time if it sees an edit to a file with the same mod_time as the last edit. TODO: determine the valid charset for filenames and for usernames. TODO: use the --force-log option when appropriate. TODO: Allow use of SVN::* or other libraries if present. The current method of shelling out to the "svn" program is very slow and doesn't allow for modifying date/time and user (so far as I can see--perhaps there's a property that can be edited on the changeset, not sure). =head1 AUTHOR Barrie Slaymaker <barries@slaysys.com> =head1 COPYRIGHT Copyright (c) 2000, 2001, 2002 Perforce Software, Inc. All rights reserved. See L<VCP::License|VCP::License> (C<vcp help license>) for the terms of use. =cut 1
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 6118 | Dimitry Andric | Integ from //public/revml to //guest/dimitry_andric/revml/main. | ||
//guest/perforce_software/revml/lib/VCP/Dest/svn.pm | |||||
#2 | 5404 | Barrie Slaymaker |
- SVN support added - Makefile gives clearer notices about missing optional prereqs. - VCP::Filter::labelmap and VCP::Filter::map: <<skip>> replaces deprecated <<delete>> to be clearer that no revisions are deleted from either repository but some just are skipped and not inserted. - VCP::Filter::map: support added for SVN-like branch labels - VCP::Source: support added for ISO8601 timestamps emitted by SVN. |
||
#1 | 5343 | Barrie Slaymaker | - cvs branched to svn (non functional) | ||
//guest/perforce_software/revml/lib/VCP/Dest/cvs.pm | |||||
#72 | 4507 | Barrie Slaymaker |
- RevML: - added <action>, removed <delete>, <placeholder> and <move> - added <from_id> for clones (and eventually merge actions) - Simplified DTD (can't branch DTD based on which action any more) - VCP::Source::cvs, VCP::Filter::changesets and VCP::Dest::p4 support from_id in <action>clone</action> records - VCP::Dest::perl_data added - VCP::Rev::action() "branch" added, no more undefined action strings - "placeholder" action removed |
||
#71 | 4227 | Barrie Slaymaker |
- VCP::Dest::cvs now handles a module name with no trailing "/..." (reported by Alexandros Karypidis karypid inf uth gr). - VCP::Dest::cvs now handles a missing filespec (module name) if the source repository passed along a rev_root |
||
#70 | 4127 | Barrie Slaymaker |
- VCP::Dest::cvs now forces commits so that unchanged files will be committed. |
||
#69 | 4126 | Barrie Slaymaker |
- Comments with leading hyphens and embedded quotes are now tested for - VCP::Dest::cvs now handles comments with embedded double quotes on Win32 |
||
#68 | 4021 | Barrie Slaymaker |
- Remove all phashes and all base & fields pragmas - Work around SWASHGET error |
||
#67 | 4012 | Barrie Slaymaker | - Remove dependance on pseudohashes (deprecated Perl feature) | ||
#66 | 3970 | Barrie Slaymaker |
- VCP::Source handles rev queing, uses disk to reduce RAM - Lots of other fixes |
||
#65 | 3930 | Barrie Slaymaker |
- VCP::Source::cvs and VCP::Dest::p4 handle cloning deletes - "placeholder" actions and is_placeholder_rev() deprecated in favor of is_branch_rev() and is_clone_rev(). - Misc cleanups and minor bugfixes |
||
#64 | 3908 | Barrie Slaymaker | - Debugging cleanups | ||
#63 | 3855 | Barrie Slaymaker |
- vcp scan, filter, transfer basically functional - Need more work in re: storage format, etc, but functional |
||
#62 | 3850 | Barrie Slaymaker | - No longer stores all revs in memory | ||
#61 | 3837 | Barrie Slaymaker | - Improved progress bar support | ||
#60 | 3813 | Barrie Slaymaker | - VCP::Rev::previous() is no more | ||
#59 | 3812 | Barrie Slaymaker | - VCP::Dest::* no longer need VCP::Rev->previous() | ||
#58 | 3811 | Barrie Slaymaker | - fetch_*() and get_rev() renamed get_source_file() | ||
#57 | 3809 | Barrie Slaymaker | - compare_base_revs() now always called with 2 parameters | ||
#56 | 3805 | Barrie Slaymaker | - VCP::Revs::fetch_files() removed | ||
#55 | 3706 | Barrie Slaymaker | - VCP gives some indication of output progress (need more) | ||
#54 | 3460 | Barrie Slaymaker |
- Revamp Plugin/Source/Dest hierarchy to allow for reguritating options in to .vcp files |
||
#53 | 3410 | Barrie Slaymaker |
- Minor win32 adaptation - More aggressive filesystem cleanup |
||
#52 | 3384 | John Fetkovich | moved setting of default repo_id | ||
#51 | 3285 | John Fetkovich |
In 'sub new' constructor, Only call parse_cvs_repo_spec if a $spec is provided. parse_cvs_repo_spec also now sets repo_id. |
||
#50 | 3278 | John Fetkovich | split 'sub init' out from 'sub new' | ||
#49 | 3208 | John Fetkovich | documentation (pod) fixes. | ||
#48 | 3194 | John Fetkovich | pod fix | ||
#47 | 3165 | Barrie Slaymaker | Don't commit so often but do tell the user what's going on. | ||
#46 | 3155 | Barrie Slaymaker |
Convert to logging using VCP::Logger to reduce stdout/err spew. Simplify & speed up debugging quite a bit. Provide more verbose information in logs. Print to STDERR progress reports to keep users from wondering what's going on. Breaks test; halfway through upgrading run3() to an inline function for speed and for VCP specific features. |
||
#45 | 3133 | Barrie Slaymaker |
Make destinations call back to sources to check out files to simplify the architecture (is_metadata_only() no longer needed) and make it more optimizable (checkouts can be batched). |
||
#44 | 2973 | Barrie Slaymaker | Fix handling of branched but unchanged files | ||
#43 | 2972 | Barrie Slaymaker | Interim checkin | ||
#42 | 2926 | John Fetkovich |
remove --state-location switch add --db-dir and --repo-id switches build state location from concatenation of those two. |
||
#41 | 2901 | Barrie Slaymaker |
Make VCP::Dest::cvs use more persistant state to handle boundary conditions better. |
||
#40 | 2872 | Barrie Slaymaker | Improve VCP::Dest::cvs branch handling | ||
#39 | 2838 | John Fetkovich | Use parse_options rather than using Getopt::Long directly. | ||
#38 | 2802 | John Fetkovich |
Added a source_repo_id to each revision, and repo_id to each Source and Dest. The repo_ids include repository type (cvs,p4,revml,vss,...) and the repo_server fields. Changed the $self->...->set() and $self->...->get() lines in VCP::Dest::* to pass in a conglomerated key value, by passing in the key as an ARRAY ref. Also various restructuring in VCP::DB.pm, VCP::DB_file.pm and VCP::DB_file::sdbm.pm related to this change. |
||
#37 | 2774 | Barrie Slaymaker | Update HeadRevDB on submit/commit/write | ||
#36 | 2725 | Barrie Slaymaker | Start using HeadRevs.pm. | ||
#35 | 2720 | Barrie Slaymaker | Factor RevMapDB code up in to VCP::Dest. | ||
#34 | 2713 | Barrie Slaymaker | Factor RevMapDB management up in to VCP::Dest | ||
#33 | 2712 | Barrie Slaymaker |
RevMapDB works, branching seems to (pending further changes in statefulness so we can get incremental revml output without using labels in the source repo). |
||
#32 | 2706 | Barrie Slaymaker | Interim checkin | ||
#31 | 2703 | Barrie Slaymaker | use the new RevMapDB in VCP::Dest::cvs | ||
#30 | 2699 | Barrie Slaymaker | remove unnecessary dependancies | ||
#29 | 2663 | Barrie Slaymaker |
Fix mtime bug in VCP::Dest::cvs in branching code Improve temp directory management |
||
#28 | 2647 | Barrie Slaymaker | Add VCP::Dest::cvs --delete-cvsroot option | ||
#27 | 2620 | John Fetkovich | Added some error checks. | ||
#26 | 2293 | Barrie Slaymaker | Update CHANGES, TODO, improve .vcp files, add --init-cvs | ||
#25 | 2235 | Barrie Slaymaker | Debugging cvs speed reader. | ||
#24 | 2042 | Barrie Slaymaker | Basic source::p4 branching support | ||
#23 | 2026 | Barrie Slaymaker | VCP::8::cvs now supoprt branching | ||
#22 | 2015 | Barrie Slaymaker | submit changes | ||
#21 | 2009 | Barrie Slaymaker |
lots of fixes, improve core support for branches and VCP::Source::cvs now supports branches. |
||
#20 | 2006 | Barrie Slaymaker |
more preparations for branching support, handling of cvs :foo:... CVSROOT specs, misc fixes, improvements |
||
#19 | 1998 | Barrie Slaymaker | Initial, revml and core VCP support for branches | ||
#18 | 1758 | Barrie Slaymaker | Minor TODO added | ||
#17 | 1728 | Barrie Slaymaker | CVS on win32, minor bugfixes | ||
#16 | 1367 | Barrie Slaymaker | lots of docco updates | ||
#15 | 1055 | Barrie Slaymaker |
add sorting, revamp test suite, misc cleanup. Dest/revml is not portable off my system yet (need to release ...::Diff) |
||
#14 | 827 | Barrie Slaymaker | Add a test for and debug p4->cvs incremental exports. | ||
#13 | 825 | Barrie Slaymaker |
test, handle case where no revs are transferred and VCP::Dest::*::handle_footer() blew up. |
||
#12 | 811 | Barrie Slaymaker | more sensible name for a method. | ||
#11 | 723 | Barrie Slaymaker | VCP::Dest::cvs tuning and cvs and p4 bugfixes | ||
#10 | 720 | Barrie Slaymaker | Fix handling of $r->comment in VCP::Dest::cvs | ||
#9 | 705 | Barrie Slaymaker | Release 0.22. | ||
#8 | 628 | Barrie Slaymaker | Cleaned up POD in bin/vcp, added BSD-style license. | ||
#7 | 623 | Barrie Slaymaker | Prefix CVS-unfriendly tags w/ "tag_" instead of "_" | ||
#6 | 620 | Barrie Slaymaker |
Underscorify CVS tags, only warn about undeleted files if debugging. |
||
#5 | 609 | Barrie Slaymaker |
Add a file to the test procedure that it alternately added and deleted (file is named "readd"). Fixed all destinations to handle that. |
||
#4 | 480 | Barrie Slaymaker |
0.06 Wed Dec 20 23:19:15 EST 2000 - bin/vcp: Added --versions, which loads all modules and checks them for a $VERSION and print the results out. This should help with diagnosing out-of-sync modules. - Added $VERSION vars to a few modules :-). Forgot to increment any $VERSION strings. - VCP::Dest::cvs: The directory "deeply" was not being `cvs add`ed on paths like "a/deeply/nested/file", assuming "deeply" had no files in it. - VCP::Dest::revml: fixed a bug that was causing files with a lot of linefeeds to be emitted in base64 instead of deltaed. This means most text files. - Various minor cleanups of diagnostics and error messages, including exposing "Can't locate Foo.pm" when a VCP::Source or VCP::Dest module depends on a module that's not installed, as reported by Jeff Anton. |
||
#3 | 478 | Barrie Slaymaker |
0.05 Mon Dec 18 07:27:53 EST 2000 - Use `p4 labels //...@label` command as per Rober Cowham's suggestion, with the '-s' flag recommended by Christopher Siewald and Amaury.FORGEOTDARC@atsm.fr. Though it's actually something like vcp: running /usr/bin/p4 -u safari -c safari -p localhost:5666 -s files //.../NtLkly //...@compiler_a3 //.../NtLkly //...@compiler_may3 and so //on //for 50 parameters to get the speed up. I use the //.../NtLkly "file" as //a separator between the lists of files in various //revisions. Hope nobody has any files named that :-). What I should do is choose a random label that doesn't occur in the labels list, I guess. - VCP::Source::revml and VCP::Dest::revml are now binary, control code, and "hibit ASCII" (I know, that's an oxymoron) clean. The <comment>, <delta>, and <content> elements now escape anything other than tab, line feed, space, or printable chars (32 <= c <= ASCII 126) using a tag like '<char code="0x09">'. The test suite tests all this. Filenames should also be escaped this way, but I didn't get to that. - The decision whether to do deltas or encode the content in base64 is now based on how many characters would need to be escaped. - We now depend on the users' diff program to have a "-a" option to force it to diff even if the files look binary to it. I need to use Diff.pm and adapt it for use on binary data. - VCP::Dest::cvs now makes sure that no two consecutive revisions of the same file have the same mod_time. VCP::Source::p4 got so fast at pulling revisions from the repositories the test suite sets up that CVS was not noticing that files had changed. - VCP::Plugin now allows you to set a list of acceptable result codes, since we now use p4 in ways that make it return non-zero result codes. - VCP::Revs now croaks if you try to add two entries of the same VCP::Rev (ie matching filename and rev_id). - The <type> tag is now limited to "text" or "binary", and is meant to pass that level of info between foreign repositories. - The <p4_info> on each file now carries the one line p4 description of the file so that p4->p4 transferes can pick out the more detailed info. VCP::Source::p4, VCP::Dest::p4 do this. - VCP::{Source,Dest}::{p4,cvs} now set binaryness on added files properly, I think. For p4->p4, the native p4 type is preserved. For CVS sources, seeing the keyword substitution flag 'o' or 'b' implies binaryness, for p4, seeing a filetype like qr/u?x?binary/ or qr/x?tempobj/ or "resource" implies binaryness (to non-p4 destinations). NOTE: Seeing a 'o' or 'b' in a CVS source only ends up setting the 'b' option on the destination. That should be ok for most uses, but we can make it smarter for cvs->cvs transfers if need be. |
||
#2 | 468 | Barrie Slaymaker |
- VCP::Dest::p4 now does change number aggregation based on the comment field changing or whenever a new revision of a file with unsubmitted changes shows up on the input stream. Since revisions of files are normally sorted in time order, this should work in a number of cases. I'm sure we'll need to generalize it, perhaps with a time thresholding function. - t/90cvs.t now tests cvs->p4 replication. - VCP::Dest::p4 now doesn't try to `p4 submit` when no changes are pending. - VCP::Rev now prevents the same label from being applied twice to a revision. This was occuring because the "r_1"-style label that gets added to a target revision by VCP::Dest::p4 could duplicate a label "r_1" that happened to already be on a revision. - Added t/00rev.t, the beginnings of a test suite for VCP::Rev. - Tweaked bin/gentrevml to comment revisions with their change number instead of using a unique comment for every revision for non-p4 t/test-*-in-0.revml files. This was necessary to test cvs->p4 functionality. |
||
#1 | 467 | Barrie Slaymaker | Version 0.01, initial checkin in perforce public depot. |