Skip to content

refactor: remove monolithic clearReference#1678

Merged
dengbo11 merged 1 commit into
OpenAtom-Linyaps:masterfrom
reddevillg:clear_ref
Jun 18, 2026
Merged

refactor: remove monolithic clearReference#1678
dengbo11 merged 1 commit into
OpenAtom-Linyaps:masterfrom
reddevillg:clear_ref

Conversation

@reddevillg

Copy link
Copy Markdown
Collaborator

The old clearReference implementation always uses the default remote repo and ignores repo priority, which is not expected when the builder also supports repository priorities. We use clearReferenceLocal for local-only resolution and lookup remote reference via latestRemoteReference.

The old clearReference implementation always uses the default remote
repo and ignores repo priority, which is not expected when the builder
also supports repository priorities. We use clearReferenceLocal for
local-only resolution and lookup remote reference via
latestRemoteReference.

Signed-off-by: reddevillg <reddevillg@gmail.com>

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request refactors the dependency pulling and reference clearing logic by replacing the clearReference method with clearReferenceLocal across the codebase, including CLI, package manager, and runtime components. It also introduces a new clearDependency helper to handle local and remote dependency resolution. The review feedback highlights two critical issues: first, a potential silent failure in clearDependency where a successful result is incorrectly wrapped in an error after a local reference reset; second, a potential out-of-bounds vector access in semanticMatch when checking record.arch[0] without verifying if the vector is empty.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 167 to +205
std::optional<package::Reference> localRef;
auto localResult = repo.clearReference(
*fuzzyRef,
{ .forceRemote = false, .fallbackToRemote = false, .semanticMatching = true });
auto localResult = repo.clearReferenceLocal(*fuzzyRef, true);
if (localResult) {
localRef = std::move(localResult).value();
}
if (localRef && module && !repo.getLayerDir(*localRef, *module)) {
localRef.reset();
}

if (localRef && fuzzyRef->version && *fuzzyRef->version == localRef->version.toString()) {
return DependencyReference{ std::nullopt, std::move(localRef) };
}

if (!useRemote) {
if (localRef) {
return std::move(*localRef);
return DependencyReference{ std::nullopt, std::move(localRef) };
}
return LINGLONG_ERR(fmt::format("failed to get local ref {}", fuzzyRef->toString()),
localResult);
}

std::optional<package::Reference> remoteRef;
auto remoteResult = repo.clearReference(
*fuzzyRef,
{ .forceRemote = true, .fallbackToRemote = true, .semanticMatching = true });
std::optional<package::ReferenceWithRepo> remoteRef;
auto remoteResult = repo.latestRemoteReference(*fuzzyRef);
if (remoteResult) {
remoteRef = std::move(remoteResult).value();
}

bool preferRemote = remoteRef && (!localRef || remoteRef->version > localRef->version);
auto &bestRef = preferRemote ? remoteRef : localRef;

if (!bestRef) {
bool preferRemote =
remoteRef && (!localRef || remoteRef->reference.version > localRef->version);
if (!preferRemote && !localRef) {
return LINGLONG_ERR(fmt::format("ref doesn't exist {}", fuzzyRef->toString()));
}

auto pullRes = pullResolvedRef(*bestRef, repo, module);
if (pullRes) {
return std::move(*bestRef);
if (!preferRemote) {
remoteRef.reset();
}

return DependencyReference{ std::move(remoteRef), std::move(localRef) };
}

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.

high

In clearDependency, if localRef is reset because repo.getLayerDir fails, localResult still holds a successful result. Returning LINGLONG_ERR(..., localResult) when !useRemote is true will wrap a successful result, causing the caller to receive an error with a success code (0), which can lead to undefined behavior or silent failures. Additionally, if both local and remote resolution fail, the actual error from remoteResult (such as a network error) is discarded and replaced with a generic 'ref doesn't exist' message.

We should track the getLayerDir result and propagate the correct error, as well as propagate remoteResult's error if remote resolution fails.

    std::optional<package::Reference> localRef;
    auto localResult = repo.clearReferenceLocal(*fuzzyRef, true);
    if (localResult) {
        localRef = std::move(localResult).value();
    }
    utils::error::Result<package::LayerDir> layerDirResult = LINGLONG_OK;
    if (localRef && module) {
        layerDirResult = repo.getLayerDir(*localRef, *module);
        if (!layerDirResult) {
            localRef.reset();
        }
    }

    if (localRef && fuzzyRef->version && *fuzzyRef->version == localRef->version.toString()) {
        return DependencyReference{ std::nullopt, std::move(localRef) };
    }

    if (!useRemote) {
        if (localRef) {
            return DependencyReference{ std::nullopt, std::move(localRef) };
        }
        if (!localResult) {
            return LINGLONG_ERR(fmt::format("failed to get local ref {}", fuzzyRef->toString()),
                                localResult);
        }
        return LINGLONG_ERR(fmt::format("failed to get local ref {} module {}", fuzzyRef->toString(), *module),
                            layerDirResult);
    }

    std::optional<package::ReferenceWithRepo> remoteRef;
    auto remoteResult = repo.latestRemoteReference(*fuzzyRef);
    if (remoteResult) {
        remoteRef = std::move(remoteResult).value();
    }

    bool preferRemote = 
      remoteRef && (!localRef || remoteRef->reference.version > localRef->version);
    if (!preferRemote && !localRef) {
        if (!remoteResult) {
            return LINGLONG_ERR(fmt::format("failed to get remote ref {}", fuzzyRef->toString()),
                                remoteResult);
        }
        return LINGLONG_ERR(fmt::format("ref doesn't exist {}", fuzzyRef->toString()));
    }

    if (!preferRemote) {
        remoteRef.reset();
    }

    return DependencyReference{ std::move(remoteRef), std::move(localRef) };

Comment on lines +373 to +375
if (fuzzy.arch && fuzzy.arch->toString() != record.arch[0]) {
return false;
}

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.

high

If fuzzy.arch is specified but record.arch is empty, accessing record.arch[0] will cause an out-of-bounds access on the std::vector, leading to undefined behavior or a crash. We should check if record.arch is empty before accessing its first element.

    if (fuzzy.arch && (record.arch.empty() || fuzzy.arch->toString() != record.arch[0])) {
        return false;
    }

@codecov

codecov Bot commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 37.30159% with 79 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...linglong/src/linglong/builder/linglong_builder.cpp 42.69% 35 Missing and 16 partials ⚠️
libs/linglong/src/linglong/repo/ostree_repo.cpp 50.00% 6 Missing and 3 partials ⚠️
...g/src/linglong/package_manager/package_manager.cpp 0.00% 7 Missing ⚠️
libs/linglong/src/linglong/runtime/run_context.cpp 0.00% 3 Missing and 3 partials ⚠️
libs/linglong/src/linglong/cli/cli.cpp 0.00% 4 Missing and 1 partial ⚠️
.../src/linglong/package_manager/uab_installation.cpp 0.00% 0 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
...s/linglong/src/linglong/builder/linglong_builder.h 0.00% <ø> (ø)
libs/linglong/src/linglong/repo/ostree_repo.h 9.09% <ø> (-18.19%) ⬇️
.../src/linglong/package_manager/uab_installation.cpp 11.62% <0.00%> (-0.35%) ⬇️
libs/linglong/src/linglong/cli/cli.cpp 1.76% <0.00%> (-0.07%) ⬇️
libs/linglong/src/linglong/runtime/run_context.cpp 15.18% <0.00%> (-0.21%) ⬇️
...g/src/linglong/package_manager/package_manager.cpp 0.78% <0.00%> (+<0.01%) ⬆️
libs/linglong/src/linglong/repo/ostree_repo.cpp 16.64% <50.00%> (+0.70%) ⬆️
...linglong/src/linglong/builder/linglong_builder.cpp 8.71% <42.69%> (+2.52%) ⬆️

... and 2 files with indirect coverage changes

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

@reddevillg reddevillg requested review from ComixHe and dengbo11 June 18, 2026 10:01
@deepin-ci-robot

Copy link
Copy Markdown
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengbo11, reddevillg

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@dengbo11 dengbo11 merged commit 3fb455d into OpenAtom-Linyaps:master Jun 18, 2026
17 checks passed
@reddevillg reddevillg deleted the clear_ref branch June 22, 2026 01:27
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.

3 participants