Skip to content

Commit 058efcf

Browse files
authored
cli: determine archive type based on filename instead of path (microsoft#224605)
Refs microsoft#219632 Seems like PRSS sometimes(?) doesn't return the full archive name in the response. I don't reproduce this, but others consistently do. This PR removes the dependency on the URL path and instead checks for the gzip magic number in the first two bytes of the archive to figure out what to do.
1 parent 7a5f653 commit 058efcf

File tree

3 files changed

+25
-20
lines changed

3 files changed

+25
-20
lines changed

cli/src/update_service.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
use std::{ffi::OsStr, fmt, path::Path};
6+
use std::{fmt, path::Path};
77

88
use serde::{Deserialize, Serialize};
99

1010
use crate::{
1111
constants::VSCODE_CLI_UPDATE_ENDPOINT,
1212
debug, log, options, spanf,
1313
util::{
14-
errors::{AnyError, CodeError, WrappedError},
14+
errors::{wrap, AnyError, CodeError, WrappedError},
1515
http::{BoxedHttp, SimpleResponse},
1616
io::ReportCopyProgress,
17-
tar, zipper,
17+
tar::{self, has_gzip_header},
18+
zipper,
1819
},
1920
};
2021

@@ -178,10 +179,10 @@ pub fn unzip_downloaded_release<T>(
178179
where
179180
T: ReportCopyProgress,
180181
{
181-
if compressed_file.extension() == Some(OsStr::new("zip")) {
182-
zipper::unzip_file(compressed_file, target_dir, reporter)
183-
} else {
184-
tar::decompress_tarball(compressed_file, target_dir, reporter)
182+
match has_gzip_header(compressed_file) {
183+
Ok((f, true)) => tar::decompress_tarball(f, target_dir, reporter),
184+
Ok((f, false)) => zipper::unzip_file(f, target_dir, reporter),
185+
Err(e) => Err(wrap(e, "error checking for gzip header")),
185186
}
186187
}
187188

cli/src/util/tar.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
use crate::util::errors::{wrap, WrappedError};
66

77
use flate2::read::GzDecoder;
8-
use std::fs;
9-
use std::io::Seek;
8+
use std::fs::{self, File};
9+
use std::io::{Read, Seek};
1010
use std::path::{Path, PathBuf};
1111
use tar::Archive;
1212

@@ -57,16 +57,13 @@ fn should_skip_first_segment(file: &fs::File) -> Result<(bool, u64), WrappedErro
5757
}
5858

5959
pub fn decompress_tarball<T>(
60-
path: &Path,
60+
mut tar_gz: File,
6161
parent_path: &Path,
6262
mut reporter: T,
6363
) -> Result<(), WrappedError>
6464
where
6565
T: ReportCopyProgress,
6666
{
67-
let mut tar_gz = fs::File::open(path)
68-
.map_err(|e| wrap(e, format!("error opening file {}", path.display())))?;
69-
7067
let (skip_first, num_entries) = should_skip_first_segment(&tar_gz)?;
7168
let report_progress_every = num_entries / 20;
7269
let mut entries_so_far = 0;
@@ -81,7 +78,7 @@ where
8178
let mut archive = Archive::new(tar);
8279
archive
8380
.entries()
84-
.map_err(|e| wrap(e, format!("error opening archive {}", path.display())))?
81+
.map_err(|e| wrap(e, "error opening archive"))?
8582
.filter_map(|e| e.ok())
8683
.try_for_each::<_, Result<_, WrappedError>>(|mut entry| {
8784
// approximate progress based on where we are in the archive:
@@ -118,3 +115,13 @@ where
118115

119116
Ok(())
120117
}
118+
119+
pub fn has_gzip_header(path: &Path) -> std::io::Result<(File, bool)> {
120+
let mut file = fs::File::open(path)?;
121+
let mut header = [0; 2];
122+
let _ = file.read_exact(&mut header);
123+
124+
file.rewind()?;
125+
126+
Ok((file, header[0] == 0x1f && header[1] == 0x8b))
127+
}

cli/src/util/zipper.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,12 @@ fn should_skip_first_segment(archive: &mut ZipArchive<File>) -> bool {
4444
archive.len() > 1 // prefix removal is invalid if there's only a single file
4545
}
4646

47-
pub fn unzip_file<T>(path: &Path, parent_path: &Path, mut reporter: T) -> Result<(), WrappedError>
47+
pub fn unzip_file<T>(file: File, parent_path: &Path, mut reporter: T) -> Result<(), WrappedError>
4848
where
4949
T: ReportCopyProgress,
5050
{
51-
let file = fs::File::open(path)
52-
.map_err(|e| wrap(e, format!("unable to open file {}", path.display())))?;
53-
54-
let mut archive = zip::ZipArchive::new(file)
55-
.map_err(|e| wrap(e, format!("failed to open zip archive {}", path.display())))?;
51+
let mut archive =
52+
zip::ZipArchive::new(file).map_err(|e| wrap(e, "failed to open zip archive"))?;
5653

5754
let skip_segments_no = usize::from(should_skip_first_segment(&mut archive));
5855
let report_progress_every = archive.len() / 20;

0 commit comments

Comments
 (0)