CVS offline repo mergin *all* changes to main repo

Giorgos Keramidas keramida at ceid.upatras.gr
Tue May 24 18:15:15 EEST 2005


On 2005-05-24 17:28, Dimitris Glezos <glezos at ceid.upatras.gr> wrote:
>
> Γειά χαρά, μια ερώτηση για τους CVS gurus.
>
> Scenario:
> - Δύο repositories: Μία η κύρια (online) και μία προσωρινή (offline
>    κάτι σαν vendor local repo).
> - Checkout από την online την τελευταία έκδοση, checkin στην offline.
> - Πολλές αλλαγές στην offline (και πολλά check-ins).
>
> Ερώτηση:
> - Πώς μπορεί κανείς να κάνει merge back στην online όλα τα ενδιάμεσα
> checkins που έγιναν στην offline;

Αν στο online repository δουλεύει μόνο ένα άτομο, μπορείς πολύ απλά να
κάνεις overwrite τα *,v files του online repository με τα τελευταία
αντίγραφα του offline tree.

> Η ερώτηση υπονοεί προφανώς να γίνει αυτό με κάποιον τρόπο ΕΚΤΟΣ του
> να φτιαχτεί ένα script το οποίο να παίρνει τις offline αλλαγές, να
> παράγει patches για την κάθε μία και μετά να τα εφαρμόζει την
> κεντρική repo.

Αν στο online repository δουλεύουν πολλά άτομα, αυτή είναι η μόνη
επιλογή, για να πάρουν σωστό revision number οι νέες αλλαγές.

> Ωστόσο, αν υπάρχει τέτοιο script, θα χαρώ πολύ να το χρησιμοποιήσω.
> Αν όχι, θα αναγκαστώ να το φτιάξω.

Μπορεί να σε βοηθήσουν ένα σετ από scripts που είχα φτιάξει κάποτε για να
βλέπω σύντομα τις αλλαγές σε ένα repository:

% #!/usr/bin/perl
%
% $rcsfile = undef;
%
% @log = ();
%
% while (defined($line = <STDIN>)) {
%     chomp $line;
%     if ($line =~ m/^Working file: /) {
%         $line =~ s/^Working file: //;
%         $rcsfile = $line;
%     } elsif ($line =~ m/^----------------------------/) {
%
%         die "expecting data"
%           unless(defined($line = <STDIN>));
%         chomp $line;
%         if (defined($line =~ m/^revision /)) {
%             $line =~ s/^revision //;
%             $rev = $line;
%         } else {
%             die "expecting revision line";
%         }
%
%         die "expecting data"
%           unless(defined($line = <STDIN>));
%         chomp $line;
%         if (defined($line =~ m/^date: /)) {
%             $line =~ s/^date: //;
%             $date = $line;
%             $date =~ s/^([^;]*); .*$/$1/;
%             $date =~ s,[/: ],.,g;
%             $author = $line;
%             $author =~ s/^.*author: ([^\s;]*);.*$/$1/;
%         } else {
%             die "expecting date: line";
%         }
%
%         $entry = [$rcsfile, $rev, $date, $author];
%         push @log, $entry;
%     }
% }
%
% print "$#log entries.\n";
% foreach $ent (sort {
%     my ($sa, $sb) = ($a->[2], $b->[2]);
%     $sa =~ s/\.//g;
%     $sb =~ s/\.//g;
%     $sa <=> $sb;
% } @log) {
%     $rcsfile = $ent->[0];
%     $rev = $ent->[1];
%     $date = $ent->[2];
%     $author = $ent->[3];
%     print "$date $rcsfile $rev $author\n";
% }

Το αποτέλεσμα, όταν αυτό το script πάρει στο stdin την έξοδο μιας "cvs log"
εντολής είναι κάτι σαν αυτό:

% orion:/d/src/contrib/top$ cvs -q log | logsort
% 201 entries
% 1997.03.23.18.51.20 ADVERTISEMENT 1.1 joerg
% 1997.03.23.18.51.20 ADVERTISEMENT 1.1.1.1 joerg
% [...]
% 2004.07.01.09.12.38 top.c 1.11 alfred
% 2004.07.01.09.12.38 top.h 1.3 alfred
% 2004.07.05.12.19.53 top.c 1.12 des
% 2004.07.08.16.45.55 commands.c 1.7 keramida
% 2004.07.08.16.45.55 top.c 1.13 keramida
% 2004.07.12.03.00.50 commands.c 1.8 alfred
% 2004.07.12.03.00.50 top.X 1.11 alfred
% 2004.07.12.03.00.50 top.c 1.14 alfred
% 2004.07.12.15.22.44 commands.c 1.9 alfred
% 2004.08.16.07.51.21 commands.c 1.10 alfred
% 2004.08.16.07.51.21 top.c 1.15 alfred
% 2005.03.13.13.37.02 top.X 1.12 brueffer
% 2005.03.16.01.59.33 top.X 1.11.2.1 brueffer
% 2005.04.14.15.02.03 commands.c 1.11 keramida
% 2005.04.14.15.02.03 top.c 1.16 keramida
% 2005.05.18.13.30.08 commands.c 1.12 keramida
% 2005.05.18.13.30.08 machine.h 1.7 keramida
% 2005.05.18.13.30.08 top.c 1.17 keramida
% 2005.05.18.13.48.33 display.c 1.8 keramida
% 2005.05.19.13.34.19 display.c 1.9 keramida
% orion:/d/src/contrib/top$

Αν δεις το timestamp των αλλαγών, θα παρατηρήσεις ότι κάποια από τα αρχεία
έχουν το ίδιο timestamp.  Αυτά έγιναν commit μέσα στο ίδιο δευτερόλεπτο (με
μεγάλη πιθανότητα στο ίδιο ακριβώς "cvs commit").

Έχοντας κάτι τέτοιο, είναι πανεύκολο να εξάγεις όλα τα μοναδικά "timestamps"
και τις κατάλληλες "cvs diff" εντολές για να δημιουργήσεις τα patches που
μπορούν να γίνουν commit στο δεύτερο repository για να συγχρονιστεί με το
αρχικό CVS tree.

Για παράδειγμα, τα changesets στο src/contrib/top του FreeBSD είναι:

% orion:/d/src/contrib/top$ cvs -q log | logsort | sed -e 1d | \
% awk '{print $1}' | sort | uniq -c
%   12 1997.03.23.18.51.20
%   60 1997.03.23.18.51.21
%    1 1997.03.23.18.52.52
%      [...]
%    2 2004.07.08.16.45.55
%    3 2004.07.12.03.00.50
%    1 2004.07.12.15.22.44
%    2 2004.08.16.07.51.21
%    1 2005.03.13.13.37.02
%    1 2005.03.16.01.59.33
%    2 2005.04.14.15.02.03
%    3 2005.05.18.13.30.08
%    1 2005.05.18.13.48.33
%    1 2005.05.19.13.34.19

Οι εντολές για "diff" που βγαίνουν από τις αλλαγές που έγιναν μέσα στο έτος
2005 μπορούν να "δημιουργηθούν" αυτόματα από κάτι σαν:

% orion:/d/src/contrib/top$ cvs -q log | logsort | sed -e 1d | \
%     awk '{print $1}' | sort | uniq | grep '^2005' | sh ./patchgen.sh
% cvs -D '2005/03/13 13:37:01 UTC' -D '2005/03/13 13:37:02 UTC'
% cvs -D '2005/03/16 01:59:32 UTC' -D '2005/03/16 01:59:33 UTC'
% cvs -D '2005/04/14 15:02:02 UTC' -D '2005/04/14 15:02:03 UTC'
% cvs -D '2005/05/18 13:30:07 UTC' -D '2005/05/18 13:30:08 UTC'
% cvs -D '2005/05/18 13:48:32 UTC' -D '2005/05/18 13:48:33 UTC'
% cvs -D '2005/05/19 13:34:18 UTC' -D '2005/05/19 13:34:19 UTC'

Όπου το μαγικό patchgen.sh script είναι αυτό:

% #!/bin/sh
%
% tsfmt='%Y.%m.%d.%H.%M.%S'
% cvsfmt='%Y/%m/%d %H:%M:%S UTC'
%
% while read ts ;do
%         # Find the second since Epoch that the timestamp matches
%         # and the second before that.
%
%         sec=$( date -ju -f "${tsfmt}" "${ts}" '+%s' )
%         psec=$( expr "${sec}" - 1 )
%
%         # Convert the seconds to date strings suitable for cvs -D options.
%
%         pdate=$( date -ju -f '%s' "${psec}" "+${cvsfmt}" )
%         date=$( date -ju -f '%s' "${sec}" "+${cvsfmt}" )
%
%         # Print the proper cvs invocation for generating the patch.
%
%         echo "cvs -D '${pdate}' -D '${date}'"
% done

Την έξοδο αυτή του patchgen.sh μπορείς να την ταίσεις μια-μια γραμμή σε ένα
shell για να σου "δημιουργήσει" τα κατάλληλα patches.  Αυτό το patchgen.sh
έχει ένα μικρό bug, που είμαι σίγουρος ότι κάποιος πιο καλός από μένα στα
μοντέρνα Linux εργαλεία θα το διορθώσει:

	Χρησιμοποιεί ένα BSd-specific option του date(1).  Το option -j,
	που δεν θέτει την ημερομηνία του συστήματος σε αυτή που δέχεται σαν
	παράμετρο, αλλά απλώς τυπώνει το αποτέλεσμα στο stdout.

Ακόμη κι έτσι, πάντως, ελπίζω να σε βοήθησα κάπως :-)

- Γιώργος




More information about the Linux-greek-users mailing list