]> git.lizzy.rs Git - rust.git/blob - src/archive.rs
Bump serde from 1.0.86 to 1.0.87
[rust.git] / src / archive.rs
1 use std::collections::HashMap;
2 use std::fs::File;
3 use std::path::PathBuf;
4
5 use crate::prelude::*;
6
7 pub struct ArchiveConfig<'a> {
8     pub sess: &'a Session,
9     pub dst: PathBuf,
10     pub src: Option<PathBuf>,
11     pub lib_search_paths: Vec<PathBuf>,
12 }
13
14 pub struct ArchiveBuilder<'a> {
15     cfg: ArchiveConfig<'a>,
16     src_archive: Option<ar::Archive<File>>,
17     src_entries: HashMap<String, usize>,
18     builder: ar::Builder<File>,
19     update_symbols: bool,
20 }
21
22 impl<'a> ArchiveBuilder<'a> {
23     pub fn new(cfg: ArchiveConfig<'a>) -> Self {
24         let (src_archive, src_entries) = if let Some(src) = &cfg.src {
25             let mut archive = ar::Archive::new(File::open(src).unwrap());
26             let mut entries = HashMap::new();
27
28             let mut i = 0;
29             while let Some(entry) = archive.next_entry() {
30                 let entry = entry.unwrap();
31                 entries.insert(
32                     String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
33                     i,
34                 );
35                 i += 1;
36             }
37
38             (Some(archive), entries)
39         } else {
40             (None, HashMap::new())
41         };
42
43         let builder = ar::Builder::new(File::create(&cfg.dst).unwrap());
44
45         ArchiveBuilder {
46             cfg,
47             src_archive,
48             src_entries,
49             builder,
50             update_symbols: false,
51         }
52     }
53
54     pub fn src_files(&self) -> Vec<String> {
55         self.src_entries.keys().cloned().collect()
56     }
57
58     pub fn remove_file(&mut self, name: &str) {
59         let file = self.src_entries.remove(name);
60         assert!(
61             file.is_some(),
62             "Tried to remove file not existing in src archive",
63         );
64     }
65
66     pub fn update_symbols(&mut self) {
67         self.update_symbols = true;
68     }
69
70     pub fn build(mut self) {
71         // Add files from original archive
72         if let Some(mut src_archive) = self.src_archive {
73             for (_entry_name, entry_idx) in self.src_entries.into_iter() {
74                 let entry = src_archive.jump_to_entry(entry_idx).unwrap();
75                 let orig_header = entry.header();
76                 let mut header =
77                     ar::Header::new(orig_header.identifier().to_vec(), orig_header.size());
78                 header.set_mtime(orig_header.mtime());
79                 header.set_uid(orig_header.uid());
80                 header.set_gid(orig_header.gid());
81                 header.set_mode(orig_header.mode());
82                 self.builder.append(&header, entry).unwrap();
83             }
84         }
85
86         // Finalize archive
87         std::mem::drop(self.builder);
88
89         // Run ranlib to be able to link the archive
90         let status = std::process::Command::new("ranlib")
91             .arg(self.cfg.dst)
92             .status()
93             .expect("Couldn't run ranlib");
94         assert!(
95             status.success(),
96             "Ranlib exited with code {:?}",
97             status.code()
98         );
99     }
100 }