Skip to content

feat: add File Store, implement Tag, Resolve, Exists#317

Closed
wangxiaoxuan273 wants to merge 15 commits into
oras-project:mainfrom
wangxiaoxuan273:file-store
Closed

feat: add File Store, implement Tag, Resolve, Exists#317
wangxiaoxuan273 wants to merge 15 commits into
oras-project:mainfrom
wangxiaoxuan273:file-store

Conversation

@wangxiaoxuan273

@wangxiaoxuan273 wangxiaoxuan273 commented Dec 15, 2025

Copy link
Copy Markdown
Contributor

Part of #37

Added File Store to oras-dotnet. Implemented Tag, Resolve, Exists, Add and Close methods. Adding a directory is not yet supported and will be added in a future PR.

Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
@codecov

codecov Bot commented Dec 15, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.24138% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.51%. Comparing base (ca1e9aa) to head (a0cb57a).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/OrasProject.Oras/Content/File/Store.cs 90.81% 15 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #317      +/-   ##
==========================================
+ Coverage   91.45%   91.51%   +0.06%     
==========================================
  Files          61       66       +5     
  Lines        2586     2818     +232     
  Branches      345      369      +24     
==========================================
+ Hits         2365     2579     +214     
- Misses        137      152      +15     
- Partials       84       87       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
@wangxiaoxuan273 wangxiaoxuan273 changed the title feat: file store constructors and close feat: add File Store, implement Tag, Resolve, Exists Jan 5, 2026
@wangxiaoxuan273 wangxiaoxuan273 marked this pull request as ready for review January 5, 2026 08:49
Copilot AI review requested due to automatic review settings January 5, 2026 08:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a file-based storage implementation for ORAS .NET, adding the Store class that provides content-addressable storage backed by the file system. The implementation includes methods for adding files, tagging descriptors, resolving tags, and checking content existence.

Key changes:

  • Added Store class with Add, Tag, Resolve, Exists, and Close operations for file-based storage
  • Introduced four new exception types to handle store-specific error conditions
  • Added AnnotationTitle constant to Descriptor for OCI image title annotation support

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 18 comments.

Show a summary per file
File Description
src/OrasProject.Oras/Content/File/Store.cs Core file store implementation with named content tracking, fallback storage, and thread-safe operations
src/OrasProject.Oras/Oci/Descriptor.cs Added AnnotationTitle constant for OCI-compliant image title annotations
src/OrasProject.Oras/Exceptions/DuplicateNameException.cs New exception thrown when attempting to add a duplicate name to the store
src/OrasProject.Oras/Exceptions/MissingNameException.cs New exception thrown when a required name parameter is missing
src/OrasProject.Oras/Exceptions/MissingReferenceException.cs New exception thrown when a required reference parameter is missing
src/OrasProject.Oras/Exceptions/StoreClosedException.cs New exception thrown when operations are attempted on a closed store
tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs Comprehensive test suite covering store lifecycle, operations, validation, and error handling
tests/OrasProject.Oras.Tests/Exceptions/ExceptionTest.cs Tests verifying the new exception types can be instantiated and thrown correctly

Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs Outdated
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs Outdated
Comment thread src/OrasProject.Oras/Content/File/Store.cs Outdated
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 15 comments.

Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Exceptions/MissingReferenceException.cs
Comment thread src/OrasProject.Oras/Oci/Descriptor.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs Outdated

@cshung cshung left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've identified a TOCTOU (Time-of-Check to Time-of-Use) race condition that needs to be addressed before approval.

}

// if the target has name, check if the name exists.
if (target.Annotations != null && target.Annotations.TryGetValue(Descriptor.AnnotationTitle, out var name))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current IsClosedSet() check might not fully address TOCTOU (Time-of-Check to Time-of-Use) race conditions.

Consider a situation where:

  • Thread 1 is checking whether an element exists in the store (ExistsAsync)
  • Thread 2 is simultaneously closing the store (Close())

Expected outcomes:

  1. Thread 1 completes before close → returns result successfully
  2. Thread 2 closes first → Thread 1 receives StoreClosedException

However, if operations interleave as:

  1. Thread 1 calls IsClosedSet() → passes (store not closed yet)
  2. Thread 2 calls Close() → deletes files via _tmpFiles
  3. Thread 1 proceeds to file access → file access exception

This is the classic TOCTOU vulnerability where the time-of-check ≠ time-of-use. The IsClosedSet() flag alone cannot prevent this race. Store access and closing operations need proper mutual exclusion (locks, semaphores, etc.).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment Andrew. I have added a semaphore against Close(), so that when other operations are in process, Close() cannot be called, and when Close() is in process, other operations cannot be called. Can you take a look and see if there's any possible improvement?

/// </summary>
private class NameStatus
{
public SemaphoreSlim Semaphore { get; } = new(1, 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SemaphoreSlim created here is never disposed. When Store.Dispose() is called, these semaphores remain in memory and could lead to memory leak

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this. Made NameStatus to implement IDisposable, and called Dispose when calling Store.Close().

Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Signed-off-by: Xiaoxuan Wang <wangxiaoxuan119@gmail.com>
Copilot AI review requested due to automatic review settings January 14, 2026 06:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread tests/OrasProject.Oras.Tests/Content/File/StoreTest.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
Comment thread src/OrasProject.Oras/Content/File/Store.cs
@wangxiaoxuan273

Copy link
Copy Markdown
Contributor Author

superseded by #328

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants