While doing a test trying to create and press a vpatch with Linux kernel source, I discovered that vpatch cannot handle files in the press root directory1. The reason for this lies in the Path_Prefix function:
function Path_Prefix(Pathname: String;
Suffix: Positive) return String is
Pos: Natural := Pathname'Last;
begin
for I in 1..Suffix loop
Pos := Ada.Strings.Fixed.Index(Pathname, "/",
From => Pos,
Going => Ada.Strings.Backward);
if Pos = 0 then
return Pathname;
end if;
Pos := Pos - 1;
end loop;
return Pathname(Pathname'First .. Pos);
end;
The function is written in such a way that when Suffix argument is greater then the number of slash-delimited components in the path, it will incorrectly return the unmodified Pathname argument2. Even though vpatch calls Path_Prefix with Suffix of 1 only, this still triggers the failure case with files in the press directory, forcing creation of directories with the intended names of the files instead:
if Has_Input_File then
Close(In_F);
Dirs.Delete_File(To_F_Name);
else
if not Dirs.Exists(Path_Prefix(To_F_Name, 1)) then
Dirs.Create_Path(Path_Prefix(To_F_Name, 1));
end if;
end if;
My vpatch simplifies code a bit, replacing Path_Prefix with Directory_Name (after unix dirname(1)), which correctly handles the case of missing directory components of the path:
function Directory_Name(Pathname: String) return String is
Pos: Natural := Pathname'Last;
begin
Pos := Ada.Strings.Fixed.Index(Pathname, "/",
From => Pos,
Going => Ada.Strings.Backward);
if Pos = 0 then
return Dirs.Current_Directory;
end if;
return Pathname(Pathname'First .. Pos);
end;
Additionally, I fixed a bug with handling of empty vpatches - a cryptic error was thrown on reading them before:
@@ -651,6 +647,7 @@
begin
Read_Loop:
loop
+ exit Read_Loop when End_Of_File;
declare
S: String := Get_Line;
begin
@@ -659,7 +656,6 @@
H: Header := Get_Header;
begin
Process_Hunks_For_Header(H);
- exit Read_Loop when End_Of_File;
end;
else
Put_Line("Prelude: " & S);
With the fix, empty vpatch files are silently ignored. If you wish to have an explicit error in this case, please write in.
The vpatch and seal are available here:
curl 'http://bvt-trace.net/vpatches/vtools_fixes_rootdir_files.vpatch' > vtools_fixes_rootdir_files.vpatch curl 'http://bvt-trace.net/vpatches/vtools_fixes_rootdir_files.vpatch.bvt.sig' > vtools_fixes_rootdir_files.vpatch.bvt.sig
Nice work ; and though the general principle in theory is "one fix per patch", I suspect the problems with too-lengthy patch chains that principle could lead in practice very much justify the merging of small / cosmetic secondary issues into a main fix.
I think that for smaller fixes like that having a separate vpatch (taking into account potential future regrinds, etc.) is not justified. In worst case (that is, the smaller fix turned out incorrect) I would just redo the vpatch once again. In general, I always had the impression that vpatches were meant to be on average bigger than git commits - more like git branches at merge time.
[...] vtools included in starter_v_2 are pressed to the current head, which is vtools_fixes_rootdir_files.vpatch (thank you, bvt!). This new press includes quite a few fixes, all courtesy of bvt: creating [...]