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 [...]