1+ use std:: collections:: HashSet ;
12use std:: fs;
23use std:: fs:: File ;
34use std:: io:: { Cursor , Result , Write as IoWrite , Write } ;
45use std:: ops:: Deref ;
5- use std:: path:: Path ;
6+ use std:: path:: { Path , PathBuf } ;
67
78use ar:: { Builder as ArBuilder , Header as ArHeader } ;
89use flate2:: write:: GzEncoder ;
910use flate2:: Compression ;
10- use path_slash:: { PathBufExt , PathExt as _} ;
11+ use path_slash:: PathExt as _;
1112use regex:: Regex ;
1213use tar:: { Builder as TarBuilder , EntryType , Header as TarHeader } ;
1314use walkdir:: WalkDir ;
1415
1516use crate :: input:: data:: DataInfo ;
1617use crate :: input:: filter_by_excludes;
18+ use crate :: PackageInfo ;
1719
1820pub trait AppendData {
1921 fn append_data ( & mut self , details : & DataInfo , mtime : u64 ) -> Result < ( ) > ;
@@ -30,40 +32,27 @@ where
3032 let gz = GzEncoder :: new ( & mut data_tar_gz, Compression :: default ( ) ) ;
3133 let mut tar = TarBuilder :: new ( gz) ;
3234
33- append_dirs (
34- & mut tar,
35- & format ! ( "usr/palm/applications/" ) ,
36- Option :: < & Path > :: None ,
37- mtime,
38- ) ?;
35+ let mut dir_entries: HashSet < PathBuf > = HashSet :: new ( ) ;
36+
3937 append_tree (
4038 & mut tar,
4139 format ! ( "usr/palm/applications/{}/" , info. app) ,
4240 & details. app . path ,
41+ & mut dir_entries,
4342 details. excludes . as_ref ( ) ,
43+ mtime,
4444 ) ?;
4545 for service in & details. services {
4646 append_tree (
4747 & mut tar,
4848 format ! ( "usr/palm/services/{}/" , service. info. id) ,
4949 & service. path ,
50+ & mut dir_entries,
5051 details. excludes . as_ref ( ) ,
52+ mtime,
5153 ) ?;
5254 }
53-
54- append_dirs (
55- & mut tar,
56- & format ! ( "usr/palm/packages/{}/" , info. id) ,
57- Some ( Path :: new ( "usr/palm" ) ) ,
58- mtime,
59- ) ?;
60- let mut tar_header = TarHeader :: new_gnu ( ) ;
61- tar_header. set_path ( format ! ( "usr/palm/packages/{}/packageinfo.json" , info. id) ) ?;
62- tar_header. set_mode ( 0o100644 ) ;
63- tar_header. set_size ( details. package_data . len ( ) as u64 ) ;
64- tar_header. set_mtime ( mtime) ;
65- tar_header. set_cksum ( ) ;
66- tar. append ( & tar_header, details. package_data . deref ( ) ) ?;
55+ append_package_info ( & mut tar, & mut dir_entries, info, details, mtime) ?;
6756 drop ( tar) ;
6857
6958 let mut ar_header = ArHeader :: new ( b"data.tar.gz" . to_vec ( ) , data_tar_gz. len ( ) as u64 ) ;
7665fn append_dirs < W , P > (
7766 tar : & mut TarBuilder < W > ,
7867 path : P ,
79- path_stop : Option < & Path > ,
68+ dir_entries : & mut HashSet < PathBuf > ,
8069 mtime : u64 ,
8170) -> Result < ( ) >
8271where
@@ -87,36 +76,54 @@ where
8776 let empty = Vec :: < u8 > :: new ( ) ;
8877 let mut p = path. as_ref ( ) ;
8978 while p != Path :: new ( "" ) {
90- if let Some ( s) = path_stop {
91- if p == s {
92- break ;
93- }
79+ if dir_entries. contains ( p) {
80+ break ;
9481 }
9582 stack. insert ( 0 , p) ;
83+ dir_entries. insert ( p. to_path_buf ( ) ) ;
9684 if let Some ( parent) = p. parent ( ) {
9785 p = parent;
9886 }
9987 }
10088 for p in stack {
10189 let mut header = TarHeader :: new_gnu ( ) ;
102- header. set_path ( format ! ( "{}/" , p. to_slash_lossy( ) ) ) ?;
90+ let mut dir = String :: from ( p. to_slash_lossy ( ) ) ;
91+ if !dir. ends_with ( '/' ) {
92+ dir. push ( '/' ) ;
93+ }
94+ header. set_path ( & dir) ?;
10395 header. set_entry_type ( EntryType :: Directory ) ;
104- header. set_mode ( 0o100755 ) ;
96+ header. set_mode ( 0o100775 ) ;
10597 header. set_size ( 0 ) ;
10698 header. set_uid ( 0 ) ;
107- header. set_gid ( 0 ) ;
99+ header. set_gid ( 5000 ) ;
108100 header. set_mtime ( mtime) ;
109101 header. set_cksum ( ) ;
102+ println ! ( "Adding {path}" , path = dir) ;
110103 tar. append ( & header, empty. deref ( ) ) ?;
111104 }
112105 return Ok ( ( ) ) ;
113106}
114107
108+ fn tar_path < S , P > ( prefix : S , path : P ) -> PathBuf
109+ where
110+ S : AsRef < str > ,
111+ P : AsRef < Path > ,
112+ {
113+ return PathBuf :: from ( format ! (
114+ "{}{}" ,
115+ prefix. as_ref( ) ,
116+ path. as_ref( ) . to_slash_lossy( )
117+ ) ) ;
118+ }
119+
115120fn append_tree < W , S , P > (
116121 tar : & mut TarBuilder < W > ,
117122 prefix : S ,
118123 path : P ,
124+ dir_entries : & mut HashSet < PathBuf > ,
119125 excludes : Option < & Regex > ,
126+ mtime : u64 ,
120127) -> Result < ( ) >
121128where
122129 W : Write ,
@@ -134,33 +141,62 @@ where
134141 let entry = entry?;
135142 let entry_type = entry. file_type ( ) ;
136143 let entry_metadata = entry. metadata ( ) ?;
137- let tar_path = format ! (
138- "{}{}" ,
139- prefix. as_ref( ) ,
140- entry
141- . path( )
142- . strip_prefix( base_path)
143- . unwrap( )
144- . to_slash_lossy( )
145- ) ;
144+ let entry_path = entry. path ( ) ;
145+ let tar_path = tar_path ( & prefix, entry_path. strip_prefix ( base_path) . unwrap ( ) ) ;
146+ if entry_type. is_dir ( ) {
147+ append_dirs ( tar, & tar_path, dir_entries, mtime) ?;
148+ } else if let Some ( parent) = tar_path. parent ( ) {
149+ append_dirs ( tar, parent, dir_entries, mtime) ?;
150+ }
146151 if entry_type. is_symlink ( ) {
147- let link_target = fs:: read_link ( entry. path ( ) ) ?;
152+ let link_target = fs:: read_link ( entry_path) ?;
153+ let mut header = TarHeader :: new_gnu ( ) ;
154+ header. set_metadata ( & entry_metadata) ;
155+ header. set_uid ( 0 ) ;
156+ header. set_gid ( 5000 ) ;
157+ header. set_cksum ( ) ;
148158 println ! (
149- "Adding symlink {tar_path} = > {} ({} bytes) " ,
150- link_target . to_slash_lossy ( ) ,
151- entry_metadata . len ( ) ,
159+ "Adding {path} - > {target} " ,
160+ path = tar_path . to_string_lossy ( ) ,
161+ target = link_target . to_string_lossy ( )
152162 ) ;
163+ tar. append_link ( & mut header, tar_path, link_target) ?;
164+ } else if entry_type. is_file ( ) {
153165 let mut header = TarHeader :: new_gnu ( ) ;
166+ header. set_path ( & tar_path) ?;
154167 header. set_metadata ( & entry_metadata) ;
168+ header. set_uid ( 0 ) ;
169+ header. set_gid ( 5000 ) ;
155170 header. set_cksum ( ) ;
156- tar. append_link ( & mut header, tar_path, link_target) ?;
157- } else if entry_type. is_dir ( ) {
158- println ! ( "Adding dir {tar_path} ({} bytes)" , entry_metadata. len( ) ) ;
159- tar. append_dir ( tar_path, entry. path ( ) ) ?;
160- } else {
161- println ! ( "Adding file {tar_path} ({} bytes)" , entry_metadata. len( ) ) ;
162- tar. append_file ( tar_path, & mut File :: open ( entry. path ( ) ) ?) ?;
171+ println ! ( "Adding {path}" , path = tar_path. to_string_lossy( ) ) ;
172+ tar. append_data ( & mut header, tar_path, & mut File :: open ( entry_path) ?) ?;
163173 }
164174 }
165175 return Ok ( ( ) ) ;
166176}
177+
178+ fn append_package_info < W > (
179+ tar : & mut TarBuilder < W > ,
180+ dir_entries : & mut HashSet < PathBuf > ,
181+ info : & PackageInfo ,
182+ details : & DataInfo ,
183+ mtime : u64 ,
184+ ) -> Result < ( ) >
185+ where
186+ W : Write ,
187+ {
188+ let package_dir = format ! ( "usr/palm/packages/{}/" , info. id) ;
189+ append_dirs ( tar, & package_dir, dir_entries, mtime) ?;
190+ let mut header = TarHeader :: new_gnu ( ) ;
191+ let pkg_info_path = format ! ( "usr/palm/packages/{}/packageinfo.json" , info. id) ;
192+ header. set_path ( & pkg_info_path) ?;
193+ header. set_mode ( 0o100644 ) ;
194+ header. set_size ( details. package_data . len ( ) as u64 ) ;
195+ header. set_mtime ( mtime) ;
196+ header. set_uid ( 0 ) ;
197+ header. set_gid ( 5000 ) ;
198+ header. set_cksum ( ) ;
199+ tar. append ( & header, details. package_data . deref ( ) ) ?;
200+ println ! ( "Adding {path}" , path = pkg_info_path) ;
201+ return Ok ( ( ) ) ;
202+ }
0 commit comments