source: branches/profile/SOURCE_TOOLS/svn_undo_depends.pl

Last change on this file was 10201, checked in by westram, 11 years ago

merge from bpcb [10195] [10197] [10199]

  • Property svn:executable set to *
File size: 4.8 KB
Line 
1#!/usr/bin/perl
2# ============================================================ #
3#                                                              #
4#   File      : svn_undo_depends.pl                            #
5#   Purpose   : undo all dependency-only changes to makefiles  #
6#                                                              #
7#   Coded by Ralf Westram (coder@reallysoft.de) in July 2013   #
8#   Institute of Microbiology (Technical University Munich)    #
9#   http://www.arb-home.de/                                    #
10#                                                              #
11# ============================================================ #
12
13my $reg_changes_depends = qr/^[+-][a-z0-9_]+\.o:\s/i;
14my $reg_is_header_start = qr/^Index:\s/i;
15my $reg_is_chunk_start = qr/^\@\@\s/i;
16
17use Carp confess;
18
19sub save_array($\@) {
20  my ($toname,$arr_r) = @_;
21
22  open(FILE,'>'.$toname) || die "can't write to file '$toname' (Reason: $!)";
23  foreach (@$arr_r) {
24    print FILE $_."\n";
25  }
26  close(FILE);
27}
28
29sub chunk_contains(\@$\$) {
30  my ($chunk_r, $reg_contains, $seen_other_changes_r) = @_;
31
32  my $skipped_first = 0;
33  my $contains = 0;
34  foreach (@$chunk_r) {
35    if ($skipped_first) {
36      if ($_ =~ $reg_contains) {
37        $contains = 1;
38      }
39      elsif (/^[+-]/o) {
40        $$seen_other_changes_r = 1;
41      }
42    }
43    else {
44      $skipped_first = 1;
45    }
46  }
47  return $contains;
48}
49
50sub is_section_end($) {
51  my ($line) = @_;
52  return ((not defined $line) or ($line =~ $reg_is_header_start) or ($line =~ $reg_is_chunk_start)) ? 1 : 0;
53}
54
55sub take($\@\@) {
56  my ($amount,$in_r,$out_r) = @_;
57
58  my $size = scalar(@$in_r);
59  if ($amount>$size) { die "Tried to take to much"; }
60  if ($amount==$size) {
61    @$out_r = @$in_r;
62    @$in_r = ();
63  }
64  else {
65    @$out_r = @$in_r[0 .. $amount-1];
66    @$in_r = @$in_r[$amount .. $size-1];
67  }
68}
69
70sub find_next_section_end(\@) {
71  my ($in_r) = @_;
72  my $idx = 1;
73  while (not is_section_end($$in_r[$idx])) {
74    $idx++;
75    die "overflow" if $idx>9999;
76  }
77  return $idx;
78}
79
80sub read_header(\@\@) {
81  my ($in_r,$out_r) = @_;
82
83  my $line = $$in_r[0];
84  if (not $line =~ $reg_is_header_start) {
85    Carp::confess "Expected header start in line '$line'";
86  }
87
88  my $length = find_next_section_end(@$in_r);
89  take($length,@$in_r,@$out_r);
90}
91
92sub read_chunk(\@\@) {
93  my ($in_r,$out_r) = @_;
94
95  my $line = $$in_r[0];
96  if (not $line =~ $reg_is_chunk_start) {
97    Carp::confess "Expected chunk start in line '$line'";
98  }
99
100  my $length = find_next_section_end(@$in_r);
101  take($length,@$in_r,@$out_r);
102}
103
104sub extract_depends(\@\@) {
105  my ($in_r,$out_r) = @_;
106
107  # drop lines before first header (e.g. mergeinfo)
108  while (not $$in_r[0] =~ $reg_is_header_start) {
109    die "no diff here" if not defined shift @$in_r;
110  }
111
112  my @header = ();
113  read_header(@$in_r, @header);
114
115  my @chunk = ();
116  read_chunk(@$in_r, @chunk);
117
118  my $count = 0;
119  while (scalar(@chunk)) {
120    my $seen_other_changes = 0;
121    if (chunk_contains(@chunk, $reg_changes_depends, $seen_other_changes)) {
122      if ($seen_other_changes==1) {
123        die if (not $header[0] =~ $reg_is_header_start);
124        print "Warning: skipped hunk with mixed changes ($')";
125      }
126      else {
127        if (scalar(@header)) {
128          push @$out_r, @header;
129          @header = ();
130        }
131        push @$out_r, @chunk;
132      }
133    }
134    @chunk = ();
135
136    if (scalar(@$in_r)) {
137      if ($$in_r[0] =~ $reg_is_header_start) {
138        read_header(@$in_r, @header);
139      }
140      read_chunk(@$in_r, @chunk);
141    }
142  }
143}
144
145sub svn_undo_depends($) {
146  my ($root) = @_;
147  chdir($root) || die "can't cd to '$root' (Reason: $!)";
148
149  my @diff = map { chomp; $_; } `svn diff`;
150
151  my @diff_depends = ();
152  extract_depends(@diff,@diff_depends);
153
154  my $ARBHOME = $ENV{ARBHOME};
155  if (defined $ARBHOME and -d $ARBHOME) {
156    print "Creating safety patch..\n";
157    my $cmd = "$ARBHOME/SOURCE_TOOLS/arb_create_patch.sh b4undodepends";
158    system($cmd)==0 || die "error executing '$cmd' (result=$?)";
159  }
160
161  {
162    my $rev_patch = 'reverted_depends.patch';
163    save_array($rev_patch, @diff_depends);
164
165    print "Reverting dependency changes..\n";
166    my $patch_options = '--strip=0 --reverse --unified --force';
167    my $cmd = "patch $patch_options";
168    open(REVERT, '|'.$cmd) || die "can't execute '$cmd' (Reason: $!)";
169    foreach (@diff_depends) { print REVERT $_."\n"; }
170    close(REVERT);
171   
172    print "Reverts saved in $rev_patch\n";
173  }
174}
175
176sub show_usage($) {
177  my ($err) = @_;
178  print "Usage: svn_undo_depends.pl rootdir\n";
179  print "Reverts all dependency updates\n";
180  print "Error: $err\n";
181  exit(0);
182}
183
184sub main() {
185  my $args = scalar(@ARGV);
186  if ($args!=1) {
187    show_usage("expected argument 'rootdir'");
188  }
189  my $root = shift @ARGV;
190  if (not -d $root) {
191    show_usage("No such directory '$root'");
192  }
193
194  svn_undo_depends($root);
195}
196
197main();
Note: See TracBrowser for help on using the repository browser.