History

feat(gix-tempfile)!: support shared permissions for parent directories

<!-- agent --> Temporary files created in shared repositories can require new parent directories. Callers need those directories to honor the repository's sharing policy even when the process umask would make them private. Replace the tuple field of `ContainingDirectory::CreateAllRaceProof` with named `retries` and `shared_repository_permissions` fields, and pass the policy to directory creation in `gix_fs`. Setting the policy to `0` preserves the previous umask behavior. Adapt the existing tempfile tests to the new variant shape.

Byron committed 2 months ago

Commit edea3751 parent 6d016874 files · +39 −9Browse files

Unified · Split

4 files
  1. gix-lock/src/acquire.rs +4 −1
  2. gix-tempfile/src/handle.rs +4 −1
  3. gix-tempfile/src/lib.rs +7 −1
  4. gix-tempfile/tests/tempfile/handle.rs +24 −6
gix-lock/src/acquire.rs+4−1
@@ -238,7 +238,10 @@ fn dir_cleanup(boundary: Option<PathBuf>) -> (ContainingDirectory, AutoRemove) { · 237 unmodified lines
238238 match boundary {
239239 None => (ContainingDirectory::Exists, AutoRemove::Tempfile),
240240 Some(boundary_directory) => (
241− ContainingDirectory::CreateAllRaceProof(Default::default()),
241+ ContainingDirectory::CreateAllRaceProof {
242+ retries: Default::default(),
243+ shared_repository_permissions: 0,
244+ },
242245 AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory },
243246 ),
244247 }
gix-tempfile/src/handle.rs+4−1
@@ -343,7 +343,10 @@ impl ContainingDirectory { · 342 unmodified lines
343343 fn resolve(self, dir: &Path) -> std::io::Result<&Path> {
344344 match self {
345345 ContainingDirectory::Exists => Ok(dir),
346− ContainingDirectory::CreateAllRaceProof(retries) => crate::create_dir::all(dir, retries, 0),
346+ ContainingDirectory::CreateAllRaceProof {
347+ retries,
348+ shared_repository_permissions,
349+ } => crate::create_dir::all(dir, retries, shared_repository_permissions),
347350 }
348351 }
349352 }
gix-tempfile/src/lib.rs+7−1
@@ -160,7 +160,13 @@ pub enum ContainingDirectory { · 159 unmodified lines
160160 Exists,
161161 /// Create the directory recursively with the given number of retries in a way that is somewhat race resistant
162162 /// depending on the amount of retries.
163− CreateAllRaceProof(create_dir::Retries),
163+ CreateAllRaceProof {
164+ /// How often to retry directory creation when other processes interfere.
165+ retries: create_dir::Retries,
166+ /// Git's parsed sharing policy for newly created directories; `0` keeps the umask permissions.
167+ /// See [`gix_fs::adjust_shared_repository_permissions()`] for the encoding.
168+ shared_repository_permissions: i32,
169+ },
164170 }
165171
166172 /// A type expressing the ways we cleanup after ourselves to remove resources we created.
gix-tempfile/tests/tempfile/handle.rs+24−6
@@ -8,7 +8,10 @@ mod mark_path { · 7 unmodified lines
88 let new_filename = target.parent().unwrap().join("file.ext");
99 let handle = gix_tempfile::mark_at(
1010 &target,
11− ContainingDirectory::CreateAllRaceProof(Default::default()),
11+ ContainingDirectory::CreateAllRaceProof {
12+ retries: Default::default(),
13+ shared_repository_permissions: 0,
14+ },
1215 AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
1316 boundary_directory: dir.path().into(),
1417 },
@@ -37,7 +40,10 @@ mod mark_path { · 22 unmodified lines
3740 let filename = dir.path().join(first_dir).join("subdir").join("file.tmp");
3841 let tempfile = gix_tempfile::mark_at(
3942 &filename,
40− ContainingDirectory::CreateAllRaceProof(Default::default()),
43+ ContainingDirectory::CreateAllRaceProof {
44+ retries: Default::default(),
45+ shared_repository_permissions: 0,
46+ },
4147 AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
4248 boundary_directory: dir.path().into(),
4349 },
@@ -65,7 +71,10 @@ mod at_path { · 21 unmodified lines
6571 let new_filename = target.parent().unwrap().join("file.ext");
6672 let mut file = gix_tempfile::writable_at(
6773 &target,
68− ContainingDirectory::CreateAllRaceProof(Default::default()),
74+ ContainingDirectory::CreateAllRaceProof {
75+ retries: Default::default(),
76+ shared_repository_permissions: 0,
77+ },
6978 AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
7079 boundary_directory: dir.path().into(),
7180 },
@@ -98,7 +107,10 @@ mod at_path { · 26 unmodified lines
98107 );
99108 let handle = gix_tempfile::writable_at(
100109 &target,
101− ContainingDirectory::CreateAllRaceProof(Default::default()),
110+ ContainingDirectory::CreateAllRaceProof {
111+ retries: Default::default(),
112+ shared_repository_permissions: 0,
113+ },
102114 AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
103115 boundary_directory: dir.path().into(),
104116 },
@@ -163,7 +175,10 @@ mod at_path { · 58 unmodified lines
163175 let filename = dir.path().join(first_dir).join("subdir").join("file.tmp");
164176 let tempfile = gix_tempfile::writable_at(
165177 &filename,
166− ContainingDirectory::CreateAllRaceProof(Default::default()),
178+ ContainingDirectory::CreateAllRaceProof {
179+ retries: Default::default(),
180+ shared_repository_permissions: 0,
181+ },
167182 AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
168183 boundary_directory: dir.path().into(),
169184 },
@@ -244,7 +259,10 @@ mod new { · 74 unmodified lines
244259 {
245260 let mut writable = gix_tempfile::new(
246261 &containing_dir,
247− ContainingDirectory::CreateAllRaceProof(Default::default()),
262+ ContainingDirectory::CreateAllRaceProof {
263+ retries: Default::default(),
264+ shared_repository_permissions: 0,
265+ },
248266 AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
249267 boundary_directory: dir.path().into(),
250268 },