@@ -421,6 +421,17 @@ func (bw *qemu) WorkspaceTar(ctx context.Context, cfg *Config, extraFiles []stri
421
421
// Now, append those files to the extraFiles list (there should be no
422
422
// duplicates)
423
423
extraFiles = append (extraFiles , licenseFiles ... )
424
+ // We inject the list of extra files to a remote file in order to use it
425
+ // with `-T` option of tar. This avoids passing too many arguments to
426
+ // the command, that would lead to an "-ash: sh: Argument list too long"
427
+ // error otherwise.
428
+ if len (extraFiles ) > 0 {
429
+ err = streamExtraFilesList (ctx , cfg , extraFiles )
430
+ if err != nil {
431
+ clog .FromContext (ctx ).Errorf ("failed to send list of extra files: %v" , err )
432
+ return nil , err
433
+ }
434
+ }
424
435
425
436
outFile , err := os .Create (filepath .Join (cfg .WorkspaceDir , "melange-out.tar" ))
426
437
if err != nil {
@@ -436,11 +447,11 @@ func (bw *qemu) WorkspaceTar(ctx context.Context, cfg *Config, extraFiles []stri
436
447
// We could just cp -a to /mnt as it is our shared workspace directory, but
437
448
// this will lose some file metadata like hardlinks, owners and so on.
438
449
// Example of package that won't work when using "cp -a" is glibc.
439
- retrieveCommand := "cd /mount/home/build && find melange-out -type p -delete 2> /dev/null || true && tar cvpf - --xattrs --acls melange-out"
450
+ retrieveCommand := "cd /mount/home/build && find melange-out -type p -delete > /dev/null 2>&1 || true && tar cvpf - --xattrs --acls melange-out"
440
451
// we append also all the necessary files that we might need, for example Licenses
441
452
// for license checks
442
- for _ , v := range extraFiles {
443
- retrieveCommand = fmt . Sprintf ( "%s %q" , retrieveCommand , v )
453
+ if len ( extraFiles ) > 0 {
454
+ retrieveCommand = retrieveCommand + " -T extrafiles.txt"
444
455
}
445
456
446
457
log := clog .FromContext (ctx )
@@ -947,6 +958,70 @@ func getWorkspaceLicenseFiles(ctx context.Context, cfg *Config, extraFiles []str
947
958
return licenseFiles , nil
948
959
}
949
960
961
+ // send to the builder the list of extra files, to avoid sending a single long
962
+ // command (avoiding "-ash: sh: Argument list too long") we will use stdin to
963
+ // stream it. this also has the upside of not relying on a single-shot connection
964
+ // to pass potentially lot of data.
965
+ // split in chunks (100 stirngs at time) in order to avoid flackiness in the
966
+ // connection.
967
+ func streamExtraFilesList (ctx context.Context , cfg * Config , extraFiles []string ) error {
968
+ writtenStrings := 0
969
+ chunkSize := 100
970
+ log := clog .FromContext (ctx )
971
+ stdout , stderr := logwriter .New (log .Warn ), logwriter .New (log .Error )
972
+ for {
973
+ session , err := cfg .SSHClient .NewSession ()
974
+ if err != nil {
975
+ clog .FromContext (ctx ).Errorf ("Failed to create session: %s" , err )
976
+ return err
977
+ }
978
+ defer session .Close ()
979
+
980
+ session .Stderr = stderr
981
+ session .Stdout = stdout
982
+ stdin , err := session .StdinPipe ()
983
+ if err != nil {
984
+ return fmt .Errorf ("failed to create stdin pipe: %v" , err )
985
+ }
986
+ cmd := "cat >> /home/build/extrafiles.txt"
987
+ if err := session .Start (cmd ); err != nil {
988
+ return fmt .Errorf ("failed to start command: %v" , err )
989
+ }
990
+
991
+ // Write 100 strings there (or remainder)
992
+ endIndex := writtenStrings + chunkSize
993
+ endIndex = min (endIndex , len (extraFiles ))
994
+ chunk := extraFiles [writtenStrings :endIndex ]
995
+
996
+ clog .FromContext (ctx ).Debugf ("sent %d of %d" ,
997
+ writtenStrings , len (extraFiles ))
998
+ if _ , err := io .Copy (stdin , strings .NewReader (
999
+ strings .Join (chunk , "\n " )+ "\n " ),
1000
+ ); err != nil {
1001
+ return fmt .Errorf ("failed to write content: %v" , err )
1002
+ }
1003
+
1004
+ if err := stdin .Close (); err != nil {
1005
+ return fmt .Errorf ("failed to close stdin: %v" , err )
1006
+ }
1007
+
1008
+ if err := session .Wait (); err != nil {
1009
+ return fmt .Errorf ("command failed: %v" , err )
1010
+ }
1011
+
1012
+ writtenStrings = endIndex
1013
+
1014
+ if writtenStrings >= len (extraFiles ) {
1015
+ break
1016
+ }
1017
+ }
1018
+
1019
+ clog .FromContext (ctx ).Debugf ("sent %d of %d" ,
1020
+ writtenStrings , len (extraFiles ))
1021
+
1022
+ return nil
1023
+ }
1024
+
950
1025
func getKernelPath (ctx context.Context ) (string , error ) {
951
1026
clog .FromContext (ctx ).Debug ("qemu: setting up kernel for vm" )
952
1027
kernel := "/boot/vmlinuz"
0 commit comments