{"record":{"id":"7901631295ef3ff6","repo":"GitoxideLabs/gitoxide","slug":"present-as-checkout-operation-isn-t-complete","errorCode":null,"errorMessage":"present as checkout operation isn't complete","messagePattern":"present as checkout operation isn't complete","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix/src/clone/checkout.rs","lineNumber":159,"sourceCode":"            bytes.show_throughput(start);\n\n            index.write(Default::default())?;\n            Ok((self.repo.take().expect(\"still present\").clone(), outcome))\n        }\n    }\n}\n\n/// Access\nimpl PrepareCheckout {\n    /// Get access to the repository while the checkout isn't yet completed.\n    ///\n    /// # Panics\n    ///\n    /// If the checkout is completed and the [`Repository`] was already passed on to the caller.\n    pub fn repo(&self) -> &Repository {\n        self.repo\n            .as_ref()\n            .expect(\"present as checkout operation isn't complete\")\n    }\n}\n\n/// Consumption\nimpl PrepareCheckout {\n    /// Persist the contained repository as is even if an error may have occurred when checking out the main working tree.\n    pub fn persist(mut self) -> Repository {\n        self.repo.take().expect(\"present and consumed once\")\n    }\n}\n\nimpl Drop for PrepareCheckout {\n    fn drop(&mut self) {\n        if let Some(repo) = self.repo.take() {\n            super::cleanup_clone_destination_on_drop(&repo, self.remove_worktree_on_drop);\n        }\n    }\n}","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix/src/clone/checkout.rs#L141-L177","documentation":"PrepareCheckout::repo() unwraps the internal Option<Repository>, asserting the repository is still present. Once checkout completed and the Repository was moved out (via main_worktree success or persist()), the invariant documented on the method (# Panics: if the checkout is completed) no longer holds and it panics.","triggerScenarios":"Calling .repo() on a PrepareCheckout after main_worktree() returned Ok and the repository was passed to the caller, or after persist() was invoked.","commonSituations":"Storing PrepareCheckout and reading repo() at multiple points; calling repo() in a Drop path after persist(); logging/inspection code run after completion.","solutions":["Only call repo() while checkout is still in progress (before main_worktree() returns Ok).","Use persist() exactly once to obtain the Repository when done.","Restructure to pass the Repository returned from main_worktree() instead of querying repo() later."],"exampleFix":"// before\nlet repo = prepare.main_worktree(...)?;\nprepare.repo(); // panics: checkout completed\n// after\nlet repo = prepare.main_worktree(...)?;\n// use `repo` directly","handlingStrategy":"type-guard","validationCode":"// Only query repo() before starting checkout:\nif !checkout_started { let repo = prepare.repo(); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Read repo() only during setup, before main_worktree().","After completion, use the Repository value returned by main_worktree().","Never call repo() after persist() or Drop."],"tags":["rust","panic","state-machine","clone-checkout"],"backgroundTag":"invalid-state-transition","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}