git-if-needed: read patches from a series file.

Change-Id: I29c87e8448f89deaab0c04678296b25013982486
diff --git a/tools/git-if-needed/tests/data/openstack/cinder/add-readme.patch b/tools/git-if-needed/tests/data/openstack/cinder/add-readme.patch
new file mode 100644
index 0000000..a6012ce
--- /dev/null
+++ b/tools/git-if-needed/tests/data/openstack/cinder/add-readme.patch
@@ -0,0 +1,21 @@
+From 8d0a6195ee106f7d18ff9f6d6d33747cf5db6250 Mon Sep 17 00:00:00 2001
+From: Peter Penchev <openstack-dev@storpool.com>
+Date: Tue, 3 Dec 2019 16:11:08 +0200
+Subject: [PATCH 1/3] Add a README file.
+
+Change-Id: I81a662baca9813772f6b1b83a1c034bd1fe6d53f
+---
+ README.txt | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 README.txt
+
+diff --git a/README.txt b/README.txt
+new file mode 100644
+index 0000000..4dd1ef7
+--- /dev/null
++++ b/README.txt
+@@ -0,0 +1 @@
++This is a file.
+-- 
+2.24.0
+
diff --git a/tools/git-if-needed/tests/data/openstack/cinder/another-file.patch b/tools/git-if-needed/tests/data/openstack/cinder/another-file.patch
new file mode 100644
index 0000000..7286cdb
--- /dev/null
+++ b/tools/git-if-needed/tests/data/openstack/cinder/another-file.patch
@@ -0,0 +1,21 @@
+From 5c71ff4ba69bd0b95a6f3747886f10480dc24db3 Mon Sep 17 00:00:00 2001
+From: Peter Penchev <openstack-dev@storpool.com>
+Date: Tue, 3 Dec 2019 16:11:53 +0200
+Subject: [PATCH 3/3] Add another file.
+
+Change-Id: Ieb2a7d5346a74e8af3569d08057a8c83a537a1ad
+---
+ TODO.txt | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 TODO.txt
+
+diff --git a/TODO.txt b/TODO.txt
+new file mode 100644
+index 0000000..209db4a
+--- /dev/null
++++ b/TODO.txt
+@@ -0,0 +1 @@
++Things to do. Or something.
+-- 
+2.24.0
+
diff --git a/tools/git-if-needed/tests/data/openstack/cinder/conflict-in-readme.patch b/tools/git-if-needed/tests/data/openstack/cinder/conflict-in-readme.patch
new file mode 100644
index 0000000..82039e5
--- /dev/null
+++ b/tools/git-if-needed/tests/data/openstack/cinder/conflict-in-readme.patch
@@ -0,0 +1,20 @@
+From 81dd71b0300a7819d8babf73072965cfc5d3a604 Mon Sep 17 00:00:00 2001
+From: Peter Penchev <openstack-dev@storpool.com>
+Date: Tue, 3 Dec 2019 16:12:25 +0200
+Subject: [PATCH 2/2] Modify README.txt in a different way.
+
+Change-Id: I2e216842094051a30d999bf8dfebf87810202c17
+---
+ README.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/README.txt b/README.txt
+index 4dd1ef7..b38c628 100644
+--- a/README.txt
++++ b/README.txt
+@@ -1 +1 @@
+-This is a file.
++This is a file. Or something. I guess.
+-- 
+2.24.0
+
diff --git a/tools/git-if-needed/tests/data/openstack/cinder/modify-readme.patch b/tools/git-if-needed/tests/data/openstack/cinder/modify-readme.patch
new file mode 100644
index 0000000..4c75ba2
--- /dev/null
+++ b/tools/git-if-needed/tests/data/openstack/cinder/modify-readme.patch
@@ -0,0 +1,20 @@
+From 54a7cac37658e17af661b34b541507d50a24f0c9 Mon Sep 17 00:00:00 2001
+From: Peter Penchev <openstack-dev@storpool.com>
+Date: Tue, 3 Dec 2019 16:11:21 +0200
+Subject: [PATCH 2/3] Modify the README file.
+
+Change-Id: If062e5daee091fc17d3a2cacbbbaa39522385184
+---
+ README.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/README.txt b/README.txt
+index 4dd1ef7..5e7d880 100644
+--- a/README.txt
++++ b/README.txt
+@@ -1 +1 @@
+-This is a file.
++This is a file. It contains some text.
+-- 
+2.24.0
+
diff --git a/tools/git-if-needed/tests/data/openstack/nova/add-readme.patch b/tools/git-if-needed/tests/data/openstack/nova/add-readme.patch
new file mode 100644
index 0000000..5c09fa1
--- /dev/null
+++ b/tools/git-if-needed/tests/data/openstack/nova/add-readme.patch
@@ -0,0 +1,21 @@
+From 5fdf1ec10ca56c7b58328aa1a544d9ec395bd95f Mon Sep 17 00:00:00 2001
+From: Peter Penchev <openstack-dev@storpool.com>
+Date: Tue, 3 Dec 2019 16:15:52 +0200
+Subject: [PATCH] Add a README file in another repository.
+
+Change-Id: I227fed25c0565b65ad46fa6ff4386a4547f9af45
+---
+ README.txt | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 README.txt
+
+diff --git a/README.txt b/README.txt
+new file mode 100644
+index 0000000..d4e7da7
+--- /dev/null
++++ b/README.txt
+@@ -0,0 +1 @@
++This is another file. It has no bearing on the first one.
+-- 
+2.24.0
+
diff --git a/tools/git-if-needed/tests/data/series b/tools/git-if-needed/tests/data/series
new file mode 100644
index 0000000..fbb68d7
--- /dev/null
+++ b/tools/git-if-needed/tests/data/series
@@ -0,0 +1,4 @@
+openstack/cinder/add-readme.patch
+openstack/cinder/modify-readme.patch
+openstack/nova/add-readme.patch
+openstack/cinder/another-file.patch
diff --git a/tools/git-if-needed/tests/gifn-test.pl b/tools/git-if-needed/tests/gifn-test.pl
index 5de957d..989cbfa 100755
--- a/tools/git-if-needed/tests/gifn-test.pl
+++ b/tools/git-if-needed/tests/gifn-test.pl
@@ -346,6 +346,77 @@
 	}
 }
 
+sub setup_subdir_repos($)
+{
+	my ($cfg) = @_;
+
+	$cfg->{sub}->{full}->{base} = $cfg->{subrepo}->child('full');
+	$cfg->{sub}->{full}->{cinder} =
+	    $cfg->{sub}->{full}->{base}->
+	    child('openstack')->child('cinder');
+	$cfg->{sub}->{full}->{nova} =
+	    $cfg->{sub}->{full}->{base}->
+	    child('openstack')->child('nova');
+	$cfg->{sub}->{full}->{cinder}->mkpath({ mode => 0755 });
+	$cfg->{sub}->{full}->{nova}->mkpath({ mode => 0755 });
+
+	$cfg->{sub}->{short}->{base} = $cfg->{subrepo}->child('short');
+	$cfg->{sub}->{short}->{cinder} =
+	    $cfg->{sub}->{short}->{base}->child('cinder');
+	$cfg->{sub}->{short}->{nova} =
+	    $cfg->{sub}->{short}->{base}->child('nova');
+	$cfg->{sub}->{short}->{cinder}->mkpath({ mode => 0755 });
+	$cfg->{sub}->{short}->{nova}->mkpath({ mode => 0755 });
+
+	for my $part (qw(full short)) {
+		for my $comp (qw(cinder nova)) {
+			my $dir = $cfg->{sub}->{$part}->{$comp};
+			chdir($dir) or die "Could not change into $dir: $!\n";
+			run_command @{$cfg->{git}}, 'init';
+			git_status_ok $cfg;
+		}
+	}
+}
+
+sub test_subdir($ $ $ $)
+{
+	my ($cfg, $part, $expected, $opt) = @_;
+	my $run = $expected ? 'second' : 'first';
+	my $sub = $cfg->{sub}->{$part};
+
+	say "\ntest-subdir $part $run\n";
+
+	my $any = sub {
+	    $sub->{cinder}->child('README.txt')->exists ||
+	    $sub->{nova}->child('README.txt')->exists
+	};
+	my $all = sub {
+	    $sub->{cinder}->child('README.txt')->exists &&
+	    $sub->{nova}->child('README.txt')->exists
+	};
+
+	chdir $sub->{base} or die "Could not change into $sub->{base}: $!\n";
+	if ($expected && !$all->()) {
+		die "No $part files before the second run in $sub->{base}\n";
+	} elsif (!$expected && $any->()) {
+		die "Unexpected $part files in $sub->{base}\n";
+	}
+
+	run_command @{$cfg->{gifn}}, '-s', $cfg->{data}->child('series'),
+	    @{$opt}, 'am';
+
+	if (!$all->()) {
+		my $run = $expected ? 'second' : 'first';
+		die "No $part files after the $run run in $sub->{base}\n";
+	}
+
+	for my $comp (qw(cinder nova)) {
+		chdir $sub->{$comp} or
+		    die "Could not change into $sub->{comp}: $!\n";
+		git_status_ok $cfg;
+	}
+}
+
 MAIN:
 {
 	my %opts;
@@ -361,6 +432,9 @@
 	my $repodir = File::Temp->newdir(
 	    TEMPLATE => 'gifn-test.XXXXXX',
 	    TMPDIR => 1);
+	my $subrepodir = File::Temp->newdir(
+	    TEMPLATE => 'gifn-test.XXXXXX',
+	    TMPDIR => 1);
 
 	my $cfg = {
 		cwd => $cwd,
@@ -368,6 +442,7 @@
 		gifn => [@ARGV],
 		git => ['env', "LC_MESSAGES=$locale", 'git', '--no-pager'],
 		repo => path($repodir),
+		subrepo => path($subrepodir),
 	};
 
 	$cfg->{gifn}[0] = path($cfg->{gifn}[0])->absolute;
@@ -381,6 +456,13 @@
 		test_apply $cfg, @{PATCHFILES->{more}};
 		test_already_applied $cfg, (@{PATCHFILES->{initial}}, @{PATCHFILES->{more}});
 		test_fail_to_apply $cfg, @{PATCHFILES->{conflict}};
+
+		setup_subdir_repos $cfg;
+
+		test_subdir $cfg, 'full', 0, [];
+		test_subdir $cfg, 'short', 0, ['-S'];
+		test_subdir $cfg, 'full', 1, [];
+		test_subdir $cfg, 'short', 1, ['-S'];
 	};
 	my $err = $@;
 	chdir $cwd;