Repository: dignifiedquire/async-tar (language: python)

Issue:
Fails to build on Windows
This fails to build on windows since [`async_std::os::windows::fs::symlink_file`](https://docs.rs/async-std/latest/async_std/os/windows/fs/fn.symlink_file.html) requires the `unstable` feature, but this feature is not enabled.

```rs
error[E0433]: failed to resolve: could not find `fs` in `windows`
   --> C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-tar-0.4.2\src\entry.rs:588:41
    |
588 |                 async_std::os::windows::fs::symlink_file(src, dst).await
    |                                         ^^ could not find `fs` in `windows`
    |
note: found an item that was configured out
   --> C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\async-std-1.12.0\src\os\windows\mod.rs:9:13
    |
9   |     pub mod fs;
    |
```

Offending line:
https://github.com/dignifiedquire/async-tar/blob/748fee5c70ee3aae297ff5e85ab11371bbb52407/src/entry.rs#L588

cc https://github.com/zed-industries/zed/issues/12079


Discussion / hints:
thanks for the report, can you PR a fix, adjusting the feature? 
> thanks for the report, can you PR a fix, adjusting the feature? 

Yes I can. I'll get one up as soon as possible.

In the meantime, would you prefer this feature affect all targets, or only the windows target? Probably doesn't matter that much, but just checking.

Edit: PR is up now
Edit 2: Looks like there was already a PR up for this! #35 

Fix patch:
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
deleted file mode 100644
index 045b669..0000000
--- a/.github/workflows/coverage.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-on:
-  push:
-    branches: [master]
-  pull_request:
-
-name: Code Coverage
-
-jobs:
-  coverage:
-    name: Test Coverage
-    runs-on: ubuntu-latest
-    steps:
-
-      - name: checkout source
-        uses: actions/checkout@v2
-
-      - name: Install nightly toolchain
-        uses: actions-rs/toolchain@v1
-        with:
-          toolchain: nightly
-          profile: minimal
-          override: true
-
-      - name: Run cargo-tarpaulin
-        uses: actions-rs/tarpaulin@v0.1
-        with:
-          args: '--all-features'
-
-      - name: Upload to codecov.io
-        uses: codecov/codecov-action@v2.1.0
-
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 409cd98..5ace1a3 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -15,7 +15,7 @@ jobs:
         include:
           - build: msrv
             os: ubuntu-latest
-            rust: 1.51
+            rust: 1.63
           - build: stable
             os: ubuntu-latest
             rust: stable
@@ -41,7 +41,7 @@ jobs:
       - uses: actions-rs/cargo@v1
         with:
           command: test
-  
+
   fmt:
     name: Check formatting
     runs-on: ubuntu-latest
@@ -50,7 +50,7 @@ jobs:
       - uses: actions-rs/toolchain@v1
         with:
           profile: minimal
-          toolchain: nightly
+          toolchain: stable
           components: rustfmt
           override: true
       - uses: actions-rs/cargo@v1
@@ -66,7 +66,7 @@ jobs:
       - uses: actions-rs/toolchain@v1
         with:
           profile: minimal
-          toolchain: nightly
+          toolchain: stable
           components: clippy
           override: true
       - uses: actions-rs/cargo@v1
diff --git a/Cargo.toml b/Cargo.toml
index 8e984b3..982ef9c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,12 +20,12 @@ contents are never required to be entirely resident in memory all at once.
 """
 
 [dependencies]
-async-std = "1.6.0"
+async-std = { version = "1.12.0", features = ["unstable"] }
 filetime = "0.2.8"
 pin-project = "1.0.8"
 
 [dev-dependencies]
-async-std = { version = "1.6.0", features = ["unstable", "attributes"] }
+async-std = { version = "1.12.0", features = ["unstable", "attributes"] }
 static_assertions = "1.1.0"
 tempfile = "3"
 
diff --git a/README.md b/README.md
index 1b4f212..2f645e3 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ fn main() {
 
 # MSRV
 
-Minimal stable rust version: 1.51
+Minimal stable rust version: 1.63
 
 *An increase to the MSRV is accompanied by a minor version bump*
 
diff --git a/src/archive.rs b/src/archive.rs
index 7a45a83..355be39 100644
--- a/src/archive.rs
+++ b/src/archive.rs
@@ -677,7 +677,7 @@ fn poll_skip<R: Read + Unpin>(
     while amt > 0 {
         let n = cmp::min(amt, buf.len() as u64);
         match async_std::task::ready!(Pin::new(&mut source).poll_read(cx, &mut buf[..n as usize])) {
-            Ok(n) if n == 0 => {
+            Ok(0) => {
                 return Poll::Ready(Err(other("unexpected EOF during skip")));
             }
             Ok(n) => {
diff --git a/src/builder.rs b/src/builder.rs
index c413751..fab8725 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -549,7 +549,7 @@ async fn prepare_header_link(
     link_name: &Path,
 ) -> io::Result<()> {
     // Same as previous function but for linkname
-    if let Err(e) = header.set_link_name(&link_name) {
+    if let Err(e) = header.set_link_name(link_name) {
         let data = path2bytes(link_name)?;
         if data.len() < header.as_old().linkname.len() {
             return Err(e);
@@ -591,7 +591,7 @@ async fn append_dir_all(
 ) -> io::Result<()> {
     let mut stack = vec![(src_path.to_path_buf(), true, false)];
     while let Some((src, is_dir, is_symlink)) = stack.pop() {
-        let dest = path.join(src.strip_prefix(&src_path).unwrap());
+        let dest = path.join(src.strip_prefix(src_path).unwrap());
 
         // In case of a symlink pointing to a directory, is_dir is false, but src.is_dir() will return true
         if is_dir || (is_symlink && follow && src.is_dir().await) {
diff --git a/src/entry.rs b/src/entry.rs
index 4624313..1c79013 100644
--- a/src/entry.rs
+++ b/src/entry.rs
@@ -678,7 +678,7 @@ impl<R: Read + Unpin> EntryFields<R> {
         if self.preserve_mtime {
             if let Ok(mtime) = self.header.mtime() {
                 let mtime = FileTime::from_unix_time(mtime as i64, 0);
-                filetime::set_file_times(&dst, mtime, mtime).map_err(|e| {
+                filetime::set_file_times(dst, mtime, mtime).map_err(|e| {
                     TarError::new(&format!("failed to set mtime for `{}`", dst.display()), e)
                 })?;
             }
diff --git a/src/header.rs b/src/header.rs
index 3c726a4..bc8976f 100644
--- a/src/header.rs
+++ b/src/header.rs
@@ -446,14 +446,12 @@ impl Header {
     ///
     /// May return an error if the field is corrupted.
     pub fn uid(&self) -> io::Result<u64> {
-        num_field_wrapper_from(&self.as_old().uid)
-            .map(|u| u as u64)
-            .map_err(|err| {
-                io::Error::new(
-                    err.kind(),
-                    format!("{} when getting uid for {}", err, self.path_lossy()),
-                )
-            })
+        num_field_wrapper_from(&self.as_old().uid).map_err(|err| {
+            io::Error::new(
+                err.kind(),
+                format!("{} when getting uid for {}", err, self.path_lossy()),
+            )
+        })
     }
 
     /// Encodes the `uid` provided into this header.
@@ -463,14 +461,12 @@ impl Header {
 
     /// Returns the value of the group's user ID field
     pub fn gid(&self) -> io::Result<u64> {
-        num_field_wrapper_from(&self.as_old().gid)
-            .map(|u| u as u64)
-            .map_err(|err| {
-                io::Error::new(
-                    err.kind(),
-                    format!("{} when getting gid for {}", err, self.path_lossy()),
-                )
-            })
+        num_field_wrapper_from(&self.as_old().gid).map_err(|err| {
+            io::Error::new(
+                err.kind(),
+                format!("{} when getting gid for {}", err, self.path_lossy()),
+            )
+        })
     }
 
     /// Encodes the `gid` provided into this header.
@@ -721,7 +717,7 @@ impl Header {
                 self.set_mtime(meta.mtime() as u64);
                 self.set_uid(meta.uid() as u64);
                 self.set_gid(meta.gid() as u64);
-                self.set_mode(meta.mode() as u32);
+                self.set_mode(meta.mode());
             }
             HeaderMode::Deterministic => {
                 self.set_mtime(0);
@@ -1502,7 +1498,7 @@ fn copy_path_into(mut slot: &mut [u8], path: &Path, is_link_name: bool) -> io::R
                 return Err(other("path component in archive cannot contain `/`"));
             }
         }
-        copy(&mut slot, &*bytes)?;
+        copy(&mut slot, &bytes)?;
         if &*bytes != b"/" {
             needs_slash = true;
         }
@@ -1517,7 +1513,7 @@ fn copy_path_into(mut slot: &mut [u8], path: &Path, is_link_name: bool) -> io::R
     return Ok(());
 
     fn copy(slot: &mut &mut [u8], bytes: &[u8]) -> io::Result<()> {
-        copy_into(*slot, bytes)?;
+        copy_into(slot, bytes)?;
         let tmp = std::mem::take(slot);
         *slot = &mut tmp[bytes.len()..];
         Ok(())
@@ -1565,7 +1561,7 @@ pub fn path2bytes(p: &Path) -> io::Result<Cow<[u8]>> {
 #[cfg(any(unix, target_os = "redox"))]
 /// On unix this will never fail
 pub fn path2bytes(p: &Path) -> io::Result<Cow<[u8]>> {
-    Ok(p.as_os_str().as_bytes()).map(Cow::Borrowed)
+    Ok(Cow::Borrowed(p.as_os_str().as_bytes()))
 }
 
 #[cfg(windows)]
diff --git a/src/pax.rs b/src/pax.rs
index 7c131b9..7db4774 100644
--- a/src/pax.rs
+++ b/src/pax.rs
@@ -29,8 +29,13 @@ impl<'entry> Iterator for PaxExtensions<'entry> {
 
     fn next(&mut self) -> Option<io::Result<PaxExtension<'entry>>> {
         let line = match self.data.next() {
-            Some(line) if line.is_empty() => return None,
-            Some(line) => line,
+            Some(line) => {
+                if line.is_empty() {
+                    return None;
+                } else {
+                    line
+                }
+            }
             None => return None,
         };
 


Test patch:
diff --git a/tests/all.rs b/tests/all.rs
index 6f0f87f..d738345 100644
--- a/tests/all.rs
+++ b/tests/all.rs
@@ -552,31 +552,46 @@ async fn extracting_malicious_tarball() {
     // The `tmp` subdirectory should be created and within this
     // subdirectory, there should be files named `abs_evil.txt` through
     // `abs_evil6.txt`.
-    assert!(fs::metadata(td.path().join("tmp"))
+    let tmp_root = td.path().join("tmp");
+
+    assert!(fs::metadata(&tmp_root)
         .await
         .map(|m| m.is_dir())
         .unwrap_or(false));
-    assert!(fs::metadata(td.path().join("tmp/abs_evil.txt"))
+
+    let mut entries = fs::read_dir(&tmp_root).await.unwrap();
+    while let Some(entry) = entries.next().await {
+        let entry = entry.unwrap();
+        println!("- {:?}", entry.file_name());
+    }
+
+    assert!(fs::metadata(tmp_root.join("abs_evil.txt"))
         .await
         .map(|m| m.is_file())
         .unwrap_or(false));
-    assert!(fs::metadata(td.path().join("tmp/abs_evil2.txt"))
+
+    // not present due to // being interpreted differently on windows
+    #[cfg(not(target_os = "windows"))]
+    assert!(fs::metadata(tmp_root.join("abs_evil2.txt"))
         .await
         .map(|m| m.is_file())
         .unwrap_or(false));
-    assert!(fs::metadata(td.path().join("tmp/abs_evil3.txt"))
+    assert!(fs::metadata(tmp_root.join("abs_evil3.txt"))
         .await
         .map(|m| m.is_file())
         .unwrap_or(false));
-    assert!(fs::metadata(td.path().join("tmp/abs_evil4.txt"))
+    assert!(fs::metadata(tmp_root.join("abs_evil4.txt"))
         .await
         .map(|m| m.is_file())
         .unwrap_or(false));
-    assert!(fs::metadata(td.path().join("tmp/abs_evil5.txt"))
+
+    // not present due to // being interpreted differently on windows
+    #[cfg(not(target_os = "windows"))]
+    assert!(fs::metadata(tmp_root.join("abs_evil5.txt"))
         .await
         .map(|m| m.is_file())
         .unwrap_or(false));
-    assert!(fs::metadata(td.path().join("tmp/abs_evil6.txt"))
+    assert!(fs::metadata(tmp_root.join("abs_evil6.txt"))
         .await
         .map(|m| m.is_file())
         .unwrap_or(false));
diff --git a/tests/header/mod.rs b/tests/header/mod.rs
index ad65478..d95e707 100644
--- a/tests/header/mod.rs
+++ b/tests/header/mod.rs
@@ -170,7 +170,7 @@ fn set_path() {
 #[test]
 fn set_ustar_path_hard() {
     let mut h = Header::new_ustar();
-    let p = Path::new("a").join(&vec!["a"; 100].join(""));
+    let p = Path::new("a").join(vec!["a"; 100].join(""));
     t!(h.set_path(&p));
     let path = t!(h.path());
     let actual: &Path = path.as_ref().into();