1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//! Typed failures for branch create, delete, and upstream configuration.
use thiserror::Error;
use crate::objects::ObjectId;
/// Branch create, delete, and upstream failures.
#[derive(Debug, Error, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum BranchError {
/// `refs/heads/<name>` already exists and `force` was not set.
#[error("branch '{name}' already exists")]
AlreadyExists {
/// Short branch name.
name: String,
},
/// `refs/heads/<name>` does not exist.
#[error("no branch named '{name}'")]
NotFound {
/// Short branch name.
name: String,
},
/// The branch name failed ref-format validation.
#[error("invalid branch name '{name}': {reason}")]
InvalidName {
/// User-supplied short name.
name: String,
/// Human-readable ref-format validation detail.
reason: String,
},
/// Safe delete found commits not reachable from the merge base.
#[error("the branch '{name}' is not fully merged into '{base}'")]
NotFullyMerged {
/// Short branch name.
name: String,
/// Display name of the merge base (upstream or `HEAD`).
base: String,
},
/// The branch is checked out in a worktree (including the current branch on `HEAD`).
#[error("branch '{name}' is already checked out in '{worktree}'")]
CheckedOut {
/// Short branch name.
name: String,
/// Worktree path that holds the branch.
worktree: String,
},
/// No commit exists to create a branch from.
#[error("no commits yet to create a branch from")]
NoCommits,
/// Explicit [`StartPoint`] oid is missing or not a commit.
#[error("'{label}' is not a valid branch start point: {reason}")]
InvalidStartPoint {
/// Reflog label for the rejected start point.
label: String,
/// Why the oid was rejected (missing object, wrong type, etc.).
reason: String,
},
/// [`crate::porcelain::branch::set_upstream`] was given a ref that is not a local or remote-tracking branch.
#[error("upstream '{upstream}' is not a tracking branch")]
UpstreamNotTracking {
/// User-supplied upstream string.
upstream: String,
},
/// [`crate::porcelain::branch::unset_upstream`] was called when no upstream is configured.
#[error("branch '{name}' has no upstream configured")]
NoUpstream {
/// Short branch name.
name: String,
},
}
/// Start commit and reflog label for [`crate::porcelain::branch::CreateBranchOptions::start`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StartPoint {
/// Tip commit for the new or updated branch.
pub oid: ObjectId,
/// Label for `branch: Created from …` / `branch: Reset to …`.
pub label: String,
}
/// Whether creating a branch should configure `branch.<name>.remote` / `.merge`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TrackMode {
/// Follow `branch.autoSetupMerge` and fetch refspec mapping.
#[default]
Auto,
/// Always configure upstream when the start point allows it.
Always,
/// Never configure upstream.
Never,
}
/// Safe delete requires the tip to be merged; force skips the check.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeleteMode {
/// Refuse when the tip is not reachable from upstream or `HEAD`.
Safe,
/// Delete regardless of merge state.
Force,
}