Skip to content

Commit c5b9256

Browse files
committed
Merge branch 'for-junio' of git://bogomips.org/git-svn
* 'for-junio' of git://bogomips.org/git-svn: git-svn: support for git-svn propset
2 parents 4395b21 + 83c9433 commit c5b9256

File tree

3 files changed

+181
-1
lines changed

3 files changed

+181
-1
lines changed

git-svn.perl

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ sub _req_svn {
115115
$_before, $_after,
116116
$_merge, $_strategy, $_preserve_merges, $_dry_run, $_parents, $_local,
117117
$_prefix, $_no_checkout, $_url, $_verbose,
118-
$_commit_url, $_tag, $_merge_info, $_interactive);
118+
$_commit_url, $_tag, $_merge_info, $_interactive, $_set_svn_props);
119119

120120
# This is a refactoring artifact so Git::SVN can get at this git-svn switch.
121121
sub opt_prefix { return $_prefix || '' }
@@ -193,6 +193,7 @@ sub _req_svn {
193193
'dry-run|n' => \$_dry_run,
194194
'fetch-all|all' => \$_fetch_all,
195195
'commit-url=s' => \$_commit_url,
196+
'set-svn-props=s' => \$_set_svn_props,
196197
'revision|r=i' => \$_revision,
197198
'no-rebase' => \$_no_rebase,
198199
'mergeinfo=s' => \$_merge_info,
@@ -228,6 +229,9 @@ sub _req_svn {
228229
'propget' => [ \&cmd_propget,
229230
'Print the value of a property on a file or directory',
230231
{ 'revision|r=i' => \$_revision } ],
232+
'propset' => [ \&cmd_propset,
233+
'Set the value of a property on a file or directory - will be set on commit',
234+
{} ],
231235
'proplist' => [ \&cmd_proplist,
232236
'List all properties of a file or directory',
233237
{ 'revision|r=i' => \$_revision } ],
@@ -1376,6 +1380,49 @@ sub cmd_propget {
13761380
print $props->{$prop} . "\n";
13771381
}
13781382

1383+
# cmd_propset (PROPNAME, PROPVAL, PATH)
1384+
# ------------------------
1385+
# Adjust the SVN property PROPNAME to PROPVAL for PATH.
1386+
sub cmd_propset {
1387+
my ($propname, $propval, $path) = @_;
1388+
$path = '.' if not defined $path;
1389+
$path = $cmd_dir_prefix . $path;
1390+
usage(1) if not defined $propname;
1391+
usage(1) if not defined $propval;
1392+
my $file = basename($path);
1393+
my $dn = dirname($path);
1394+
my $cur_props = Git::SVN::Editor::check_attr( "svn-properties", $path );
1395+
my @new_props;
1396+
if (!$cur_props || $cur_props eq "unset" || $cur_props eq "" || $cur_props eq "set") {
1397+
push @new_props, "$propname=$propval";
1398+
} else {
1399+
# TODO: handle combining properties better
1400+
my @props = split(/;/, $cur_props);
1401+
my $replaced_prop;
1402+
foreach my $prop (@props) {
1403+
# Parse 'name=value' syntax and set the property.
1404+
if ($prop =~ /([^=]+)=(.*)/) {
1405+
my ($n,$v) = ($1,$2);
1406+
if ($n eq $propname) {
1407+
$v = $propval;
1408+
$replaced_prop = 1;
1409+
}
1410+
push @new_props, "$n=$v";
1411+
}
1412+
}
1413+
if (!$replaced_prop) {
1414+
push @new_props, "$propname=$propval";
1415+
}
1416+
}
1417+
my $attrfile = "$dn/.gitattributes";
1418+
open my $attrfh, '>>', $attrfile or die "Can't open $attrfile: $!\n";
1419+
# TODO: don't simply append here if $file already has svn-properties
1420+
my $new_props = join(';', @new_props);
1421+
print $attrfh "$file svn-properties=$new_props\n" or
1422+
die "write to $attrfile: $!\n";
1423+
close $attrfh or die "close $attrfile: $!\n";
1424+
}
1425+
13791426
# cmd_proplist (PATH)
13801427
# -------------------
13811428
# Print the list of SVN properties for PATH.

perl/Git/SVN/Editor.pm

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,40 @@ sub apply_autoprops {
288288
}
289289
}
290290

291+
sub check_attr {
292+
my ($attr,$path) = @_;
293+
my $val = command_oneline("check-attr", $attr, "--", $path);
294+
if ($val) { $val =~ s/^[^:]*:\s*[^:]*:\s*(.*)\s*$/$1/; }
295+
return $val;
296+
}
297+
298+
sub apply_manualprops {
299+
my ($self, $file, $fbat) = @_;
300+
my $pending_properties = check_attr( "svn-properties", $file );
301+
if ($pending_properties eq "") { return; }
302+
# Parse the list of properties to set.
303+
my @props = split(/;/, $pending_properties);
304+
# TODO: get existing properties to compare to
305+
# - this fails for add so currently not done
306+
# my $existing_props = ::get_svnprops($file);
307+
my $existing_props = {};
308+
# TODO: caching svn properties or storing them in .gitattributes
309+
# would make that faster
310+
foreach my $prop (@props) {
311+
# Parse 'name=value' syntax and set the property.
312+
if ($prop =~ /([^=]+)=(.*)/) {
313+
my ($n,$v) = ($1,$2);
314+
for ($n, $v) {
315+
s/^\s+//; s/\s+$//;
316+
}
317+
my $existing = $existing_props->{$n};
318+
if (!defined($existing) || $existing ne $v) {
319+
$self->change_file_prop($fbat, $n, $v);
320+
}
321+
}
322+
}
323+
}
324+
291325
sub A {
292326
my ($self, $m, $deletions) = @_;
293327
my ($dir, $file) = split_path($m->{file_b});
@@ -296,6 +330,7 @@ sub A {
296330
undef, -1);
297331
print "\tA\t$m->{file_b}\n" unless $::_q;
298332
$self->apply_autoprops($file, $fbat);
333+
$self->apply_manualprops($m->{file_b}, $fbat);
299334
$self->chg_file($fbat, $m);
300335
$self->close_file($fbat,undef,$self->{pool});
301336
}
@@ -311,6 +346,7 @@ sub C {
311346
my $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,
312347
$upa, $self->{r});
313348
print "\tC\t$m->{file_a} => $m->{file_b}\n" unless $::_q;
349+
$self->apply_manualprops($m->{file_b}, $fbat);
314350
$self->chg_file($fbat, $m);
315351
$self->close_file($fbat,undef,$self->{pool});
316352
}
@@ -333,6 +369,7 @@ sub R {
333369
$upa, $self->{r});
334370
print "\tR\t$m->{file_a} => $m->{file_b}\n" unless $::_q;
335371
$self->apply_autoprops($file, $fbat);
372+
$self->apply_manualprops($m->{file_b}, $fbat);
336373
$self->chg_file($fbat, $m);
337374
$self->close_file($fbat,undef,$self->{pool});
338375

@@ -348,6 +385,7 @@ sub M {
348385
my $fbat = $self->open_file($self->repo_path($m->{file_b}),
349386
$pbat,$self->{r},$self->{pool});
350387
print "\t$m->{chg}\t$m->{file_b}\n" unless $::_q;
388+
$self->apply_manualprops($m->{file_b}, $fbat);
351389
$self->chg_file($fbat, $m);
352390
$self->close_file($fbat,undef,$self->{pool});
353391
}

t/t9148-git-svn-propset.sh

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2014 Alfred Perlstein
4+
#
5+
6+
test_description='git svn propset tests'
7+
8+
. ./lib-git-svn.sh
9+
10+
foo_subdir2="subdir/subdir2/foo_subdir2"
11+
12+
set -e
13+
mkdir import &&
14+
(set -e ; cd import
15+
mkdir subdir
16+
mkdir subdir/subdir2
17+
touch foo # for 'add props top level'
18+
touch subdir/foo_subdir # for 'add props relative'
19+
touch "$foo_subdir2" # for 'add props subdir'
20+
svn_cmd import -m 'import for git svn' . "$svnrepo" >/dev/null
21+
)
22+
rm -rf import
23+
24+
test_expect_success 'initialize git svn' '
25+
git svn init "$svnrepo"
26+
'
27+
28+
test_expect_success 'fetch revisions from svn' '
29+
git svn fetch
30+
'
31+
32+
set_props () {
33+
subdir="$1"
34+
file="$2"
35+
shift;shift;
36+
(cd "$subdir" &&
37+
while [ $# -gt 0 ] ; do
38+
git svn propset "$1" "$2" "$file" || exit 1
39+
shift;shift;
40+
done &&
41+
echo hello >> "$file" &&
42+
git commit -m "testing propset" "$file")
43+
}
44+
45+
confirm_props () {
46+
subdir="$1"
47+
file="$2"
48+
shift;shift;
49+
(set -e ; cd "svn_project/$subdir" &&
50+
while [ $# -gt 0 ] ; do
51+
test "$(svn_cmd propget "$1" "$file")" = "$2" || exit 1
52+
shift;shift;
53+
done)
54+
}
55+
56+
57+
#The current implementation has a restriction:
58+
#svn propset will be taken as a delta for svn dcommit only
59+
#if the file content is also modified
60+
test_expect_success 'add props top level' '
61+
set_props "." "foo" "svn:keywords" "FreeBSD=%H" &&
62+
git svn dcommit &&
63+
svn_cmd co "$svnrepo" svn_project &&
64+
confirm_props "." "foo" "svn:keywords" "FreeBSD=%H" &&
65+
rm -rf svn_project
66+
'
67+
68+
test_expect_success 'add multiple props' '
69+
set_props "." "foo" \
70+
"svn:keywords" "FreeBSD=%H" fbsd:nokeywords yes &&
71+
git svn dcommit &&
72+
svn_cmd co "$svnrepo" svn_project &&
73+
confirm_props "." "foo" \
74+
"svn:keywords" "FreeBSD=%H" fbsd:nokeywords yes &&
75+
rm -rf svn_project
76+
'
77+
78+
test_expect_success 'add props subdir' '
79+
set_props "." "$foo_subdir2" svn:keywords "FreeBSD=%H" &&
80+
git svn dcommit &&
81+
svn_cmd co "$svnrepo" svn_project &&
82+
confirm_props "." "$foo_subdir2" "svn:keywords" "FreeBSD=%H" &&
83+
rm -rf svn_project
84+
'
85+
86+
test_expect_success 'add props relative' '
87+
set_props "subdir/subdir2" "../foo_subdir" \
88+
svn:keywords "FreeBSD=%H" &&
89+
git svn dcommit &&
90+
svn_cmd co "$svnrepo" svn_project &&
91+
confirm_props "subdir/subdir2" "../foo_subdir" \
92+
svn:keywords "FreeBSD=%H" &&
93+
rm -rf svn_project
94+
'
95+
test_done

0 commit comments

Comments
 (0)