@@ -282,11 +282,11 @@ pub fn process(opt: Options) !void {
282282 if (manifest ) | mani | {
283283 if (std .mem .eql (u8 , entry .path , "build.zig.zon" )) break :include_entry ;
284284 if (mani .paths ) | paths | {
285- for ( paths ) | p | {
286- if ( std . mem . startsWith ( u8 , entry . path , p )) {
287- break : include_entry ;
288- }
289- }
285+ var filter : Filter = . {
286+ . include_paths = paths ,
287+ } ;
288+
289+ if ( filter . includePath ( entry . path )) break : include_entry ;
290290 } else {
291291 for (default_ignores ) | ignore | {
292292 if (std .mem .indexOf (u8 , entry .path , ignore )) | _ | {
@@ -350,3 +350,37 @@ pub fn writeTarEntry(arc: *std.tar.Writer, entry: *std.fs.Dir.Walker.Entry) !voi
350350 else = > return ,
351351 }
352352}
353+
354+ /// exact same logic zig uses for the `paths` manifest field.
355+ /// except we use a []const []const u8 instead of a hashmap
356+ const Filter = struct {
357+ include_paths : []const []const u8 ,
358+ /// sub_path is relative to the package root.
359+ pub fn includePath (self : Filter , sub_path : []const u8 ) bool {
360+ if (self .include_paths .len == 0 ) return true ;
361+ for (self .include_paths ) | ip | {
362+ if (std .mem .eql (u8 , ip , "" )) return true ;
363+ if (std .mem .eql (u8 , ip , "." )) return true ;
364+ if (std .mem .eql (u8 , ip , sub_path )) return true ;
365+ }
366+
367+ // Check if any included paths are parent directories of sub_path.
368+ var dirname = sub_path ;
369+ while (std .fs .path .dirname (dirname )) | next_dirname | {
370+ for (self .include_paths ) | ip | {
371+ if (std .mem .eql (u8 , ip , next_dirname )) return true ;
372+ }
373+ dirname = next_dirname ;
374+ }
375+
376+ return false ;
377+ }
378+ };
379+
380+ test "includePath" {
381+ var filter : Filter = .{
382+ .include_paths = &.{"src" },
383+ };
384+ try std .testing .expect (filter .includePath ("src/core/unix/SDL_poll.c" ));
385+ try std .testing .expect (! filter .includePath (".gitignore" ));
386+ }
0 commit comments