@@ -222,6 +222,7 @@ var allTests = []func(t *testing.T, sb integration.Sandbox){
222222 testLayerLimitOnMounts ,
223223 testFrontendVerifyPlatforms ,
224224 testRunValidExitCodes ,
225+ testFileOpSymlink ,
225226}
226227
227228func TestIntegration (t * testing.T ) {
@@ -2426,6 +2427,95 @@ func testOCILayoutPlatformSource(t *testing.T, sb integration.Sandbox) {
24262427 }
24272428}
24282429
2430+ func testFileOpSymlink (t * testing.T , sb integration.Sandbox ) {
2431+ requiresLinux (t )
2432+
2433+ const (
2434+ fileOwner = 7777
2435+ fileGroup = 8888
2436+ linkOwner = 1111
2437+ linkGroup = 2222
2438+
2439+ dummyTimestamp = 42
2440+ )
2441+
2442+ dummyTime := time .Unix (dummyTimestamp , 0 )
2443+
2444+ c , err := New (sb .Context (), sb .Address ())
2445+ require .NoError (t , err )
2446+ defer c .Close ()
2447+
2448+ st := llb .Scratch ().
2449+ File (llb .Mkdir ("/foo" , 0700 ).Mkfile ("bar" , 0600 , []byte ("contents" ), llb.ChownOpt {
2450+ User : & llb.UserOpt {
2451+ UID : fileOwner ,
2452+ },
2453+ Group : & llb.UserOpt {
2454+ UID : fileGroup ,
2455+ },
2456+ })).
2457+ File (llb .Symlink ("bar" , "/baz" , llb .WithCreatedTime (dummyTime ), llb.ChownOpt {
2458+ User : & llb.UserOpt {
2459+ UID : linkOwner ,
2460+ },
2461+ Group : & llb.UserOpt {
2462+ UID : linkGroup ,
2463+ },
2464+ }))
2465+
2466+ def , err := st .Marshal (sb .Context ())
2467+ require .NoError (t , err )
2468+
2469+ destDir := t .TempDir ()
2470+
2471+ out := filepath .Join (destDir , "out.tar" )
2472+ outW , err := os .Create (out )
2473+ require .NoError (t , err )
2474+ defer outW .Close ()
2475+
2476+ _ , err = c .Solve (sb .Context (), def , SolveOpt {
2477+ Exports : []ExportEntry {
2478+ {
2479+ Type : ExporterTar ,
2480+ Output : fixedWriteCloser (outW ),
2481+ },
2482+ },
2483+ }, nil )
2484+ require .NoError (t , err )
2485+
2486+ dt , err := os .ReadFile (out )
2487+ require .NoError (t , err )
2488+ m , err := testutil .ReadTarToMap (dt , false )
2489+ require .NoError (t , err )
2490+
2491+ entry , ok := m ["bar" ]
2492+ require .True (t , ok )
2493+
2494+ dt = entry .Data
2495+ header := entry .Header
2496+ require .NoError (t , err )
2497+
2498+ require .Equal (t , []byte ("contents" ), dt )
2499+ require .Equal (t , fileOwner , header .Uid )
2500+ require .Equal (t , fileGroup , header .Gid )
2501+
2502+ entry , ok = m ["baz" ]
2503+ require .Equal (t , true , ok )
2504+
2505+ header = entry .Header
2506+ // ensure it is a symlink
2507+ require .Equal (t , tar .TypeSymlink , rune (header .Typeflag ))
2508+ // ensure it is a symlink to the proper location
2509+ require .Equal (t , "bar" , header .Linkname )
2510+
2511+ // make sure it was chowned properly
2512+ require .Equal (t , linkOwner , header .Uid )
2513+ require .Equal (t , linkGroup , header .Gid )
2514+
2515+ // ensure it was timestamped properly
2516+ require .Equal (t , dummyTime , header .ModTime )
2517+ }
2518+
24292519func testFileOpRmWildcard (t * testing.T , sb integration.Sandbox ) {
24302520 requiresLinux (t )
24312521 c , err := New (sb .Context (), sb .Address ())
0 commit comments