9
9
#include "parse-options.h"
10
10
#include "unpack-trees.h"
11
11
#include "dir.h"
12
+ #include "quote.h"
12
13
13
14
static char const * const archive_usage [] = {
14
15
N_ ("git archive [<options>] <tree-ish> [<path>...]" ),
@@ -263,6 +264,7 @@ static int queue_or_write_archive_entry(const struct object_id *oid,
263
264
struct extra_file_info {
264
265
char * base ;
265
266
struct stat stat ;
267
+ void * content ;
266
268
};
267
269
268
270
int write_archive_entries (struct archiver_args * args ,
@@ -331,19 +333,27 @@ int write_archive_entries(struct archiver_args *args,
331
333
332
334
put_be64 (fake_oid .hash , i + 1 );
333
335
334
- strbuf_reset (& path_in_archive );
335
- if (info -> base )
336
- strbuf_addstr (& path_in_archive , info -> base );
337
- strbuf_addstr (& path_in_archive , basename (path ));
338
-
339
- strbuf_reset (& content );
340
- if (strbuf_read_file (& content , path , info -> stat .st_size ) < 0 )
341
- err = error_errno (_ ("cannot read '%s'" ), path );
342
- else
343
- err = write_entry (args , & fake_oid , path_in_archive .buf ,
344
- path_in_archive .len ,
336
+ if (!info -> content ) {
337
+ strbuf_reset (& path_in_archive );
338
+ if (info -> base )
339
+ strbuf_addstr (& path_in_archive , info -> base );
340
+ strbuf_addstr (& path_in_archive , basename (path ));
341
+
342
+ strbuf_reset (& content );
343
+ if (strbuf_read_file (& content , path , info -> stat .st_size ) < 0 )
344
+ err = error_errno (_ ("cannot read '%s'" ), path );
345
+ else
346
+ err = write_entry (args , & fake_oid , path_in_archive .buf ,
347
+ path_in_archive .len ,
348
+ canon_mode (info -> stat .st_mode ),
349
+ content .buf , content .len );
350
+ } else {
351
+ err = write_entry (args , & fake_oid ,
352
+ path , strlen (path ),
345
353
canon_mode (info -> stat .st_mode ),
346
- content .buf , content .len );
354
+ info -> content , info -> stat .st_size );
355
+ }
356
+
347
357
if (err )
348
358
break ;
349
359
}
@@ -493,6 +503,7 @@ static void extra_file_info_clear(void *util, const char *str)
493
503
{
494
504
struct extra_file_info * info = util ;
495
505
free (info -> base );
506
+ free (info -> content );
496
507
free (info );
497
508
}
498
509
@@ -514,14 +525,49 @@ static int add_file_cb(const struct option *opt, const char *arg, int unset)
514
525
if (!arg )
515
526
return -1 ;
516
527
517
- path = prefix_filename (args -> prefix , arg );
518
- item = string_list_append_nodup (& args -> extra_files , path );
519
- item -> util = info = xmalloc (sizeof (* info ));
528
+ info = xmalloc (sizeof (* info ));
520
529
info -> base = xstrdup_or_null (base );
521
- if (stat (path , & info -> stat ))
522
- die (_ ("File not found: %s" ), path );
523
- if (!S_ISREG (info -> stat .st_mode ))
524
- die (_ ("Not a regular file: %s" ), path );
530
+
531
+ if (!strcmp (opt -> long_name , "add-file" )) {
532
+ path = prefix_filename (args -> prefix , arg );
533
+ if (stat (path , & info -> stat ))
534
+ die (_ ("File not found: %s" ), path );
535
+ if (!S_ISREG (info -> stat .st_mode ))
536
+ die (_ ("Not a regular file: %s" ), path );
537
+ info -> content = NULL ; /* read the file later */
538
+ } else if (!strcmp (opt -> long_name , "add-virtual-file" )) {
539
+ struct strbuf buf = STRBUF_INIT ;
540
+ const char * p = arg ;
541
+
542
+ if (* p != '"' )
543
+ p = strchr (p , ':' );
544
+ else if (unquote_c_style (& buf , p , & p ) < 0 )
545
+ die (_ ("unclosed quote: '%s'" ), arg );
546
+
547
+ if (!p || * p != ':' )
548
+ die (_ ("missing colon: '%s'" ), arg );
549
+
550
+ if (p == arg )
551
+ die (_ ("empty file name: '%s'" ), arg );
552
+
553
+ path = buf .len ?
554
+ strbuf_detach (& buf , NULL ) : xstrndup (arg , p - arg );
555
+
556
+ if (args -> prefix ) {
557
+ char * save = path ;
558
+ path = prefix_filename (args -> prefix , path );
559
+ free (save );
560
+ }
561
+ memset (& info -> stat , 0 , sizeof (info -> stat ));
562
+ info -> stat .st_mode = S_IFREG | 0644 ;
563
+ info -> content = xstrdup (p + 1 );
564
+ info -> stat .st_size = strlen (info -> content );
565
+ } else {
566
+ BUG ("add_file_cb() called for %s" , opt -> long_name );
567
+ }
568
+ item = string_list_append_nodup (& args -> extra_files , path );
569
+ item -> util = info ;
570
+
525
571
return 0 ;
526
572
}
527
573
@@ -554,6 +600,9 @@ static int parse_archive_args(int argc, const char **argv,
554
600
{ OPTION_CALLBACK , 0 , "add-file" , args , N_ ("file" ),
555
601
N_ ("add untracked file to archive" ), 0 , add_file_cb ,
556
602
(intptr_t )& base },
603
+ { OPTION_CALLBACK , 0 , "add-virtual-file" , args ,
604
+ N_ ("path:content" ), N_ ("add untracked file to archive" ), 0 ,
605
+ add_file_cb , (intptr_t )& base },
557
606
OPT_STRING ('o' , "output" , & output , N_ ("file" ),
558
607
N_ ("write the archive to this file" )),
559
608
OPT_BOOL (0 , "worktree-attributes" , & worktree_attributes ,
0 commit comments