mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-09-19 08:07:22 +03:00
create git branch name module
This commit is contained in:
parent
4299d63074
commit
11730aa7af
6
butler/Cargo.lock
generated
6
butler/Cargo.lock
generated
@ -1655,13 +1655,8 @@ name = "git-butler-tauri"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"clap",
|
||||
"colored 2.0.4",
|
||||
"dialoguer",
|
||||
"diffy",
|
||||
"dirs 5.0.1",
|
||||
"filetime",
|
||||
"fslock",
|
||||
"futures",
|
||||
@ -1696,6 +1691,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-tungstenite 0.18.0",
|
||||
"tokio-util",
|
||||
"url",
|
||||
"urlencoding",
|
||||
"uuid",
|
||||
"walkdir",
|
||||
|
@ -6,7 +6,7 @@ use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::{
|
||||
bookmarks, database, deltas, events, files, gb_repository,
|
||||
project_repository::{self, activity, conflicts, diff},
|
||||
project_repository::{self, activity, conflicts, diff, branch},
|
||||
projects, pty, search, sessions, storage, users, virtual_branches, watcher,
|
||||
};
|
||||
|
||||
@ -577,14 +577,14 @@ impl App {
|
||||
project_repository.git_match_paths(pattern)
|
||||
}
|
||||
|
||||
pub fn git_branches(&self, project_id: &str) -> Result<Vec<String>> {
|
||||
pub fn git_branches(&self, project_id: &str) -> Result<Vec<branch::LocalName>> {
|
||||
let project = self.gb_project(project_id)?;
|
||||
let project_repository = project_repository::Repository::open(&project)
|
||||
.context("failed to open project repository")?;
|
||||
project_repository.git_branches()
|
||||
}
|
||||
|
||||
pub fn git_remote_branches(&self, project_id: &str) -> Result<Vec<String>> {
|
||||
pub fn git_remote_branches(&self, project_id: &str) -> Result<Vec<branch::RemoteName>> {
|
||||
let project = self.gb_project(project_id)?;
|
||||
let project_repository = project_repository::Repository::open(&project)
|
||||
.context("failed to open project repository")?;
|
||||
|
@ -38,7 +38,7 @@ use tauri_plugin_log::{
|
||||
use thiserror::Error;
|
||||
use timed::timed;
|
||||
|
||||
use crate::project_repository::activity;
|
||||
use crate::project_repository::{activity, branch};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
@ -386,7 +386,7 @@ async fn git_match_paths(
|
||||
|
||||
#[timed(duration(printer = "debug!"))]
|
||||
#[tauri::command(async)]
|
||||
async fn git_branches(handle: tauri::AppHandle, project_id: &str) -> Result<Vec<String>, Error> {
|
||||
async fn git_branches(handle: tauri::AppHandle, project_id: &str) -> Result<Vec<branch::LocalName>, Error> {
|
||||
let app = handle.state::<app::App>();
|
||||
let branches = app
|
||||
.git_branches(project_id)
|
||||
@ -399,7 +399,7 @@ async fn git_branches(handle: tauri::AppHandle, project_id: &str) -> Result<Vec<
|
||||
async fn git_remote_branches(
|
||||
handle: tauri::AppHandle,
|
||||
project_id: &str,
|
||||
) -> Result<Vec<String>, Error> {
|
||||
) -> Result<Vec<branch::RemoteName>, Error> {
|
||||
let app = handle.state::<app::App>();
|
||||
let branches = app.git_remote_branches(project_id).with_context(|| {
|
||||
format!(
|
||||
|
113
src-tauri/src/project_repository/branch.rs
Normal file
113
src-tauri/src/project_repository/branch.rs
Normal file
@ -0,0 +1,113 @@
|
||||
use std::fmt;
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RemoteName {
|
||||
// contains name of the remote, e.x. "origin" or "upstream"
|
||||
remote: String,
|
||||
// contains name of the branch, e.x. "master" or "main"
|
||||
branch: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for RemoteName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}/{}", self.remote, self.branch)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for RemoteName {
|
||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&git2::Branch<'_>> for RemoteName {
|
||||
type Error = git2::Error;
|
||||
|
||||
fn try_from(value: &git2::Branch<'_>) -> std::result::Result<Self, Self::Error> {
|
||||
if !value.get().is_remote() {
|
||||
return Err(git2::Error::from_str("not a remote branch"));
|
||||
}
|
||||
let name = String::from_utf8(value.name_bytes()?.to_vec())
|
||||
.map_err(|e| git2::Error::from_str(&e.to_string()))?;
|
||||
|
||||
if let Some((remote, branch)) = name.split_once('/') {
|
||||
Ok(Self {
|
||||
remote: remote.to_string(),
|
||||
branch: branch.to_string(),
|
||||
})
|
||||
} else {
|
||||
Err(git2::Error::from_str("invalid remote branch name"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LocalName {
|
||||
// contains name of the branch, e.x. "master" or "main"
|
||||
branch: String,
|
||||
// contains name of the remote branch, if the local branch is tracking a remote branch
|
||||
remote: Option<RemoteName>,
|
||||
}
|
||||
|
||||
impl Serialize for LocalName {
|
||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(&self.branch)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LocalName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.branch)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&git2::Branch<'_>> for LocalName {
|
||||
type Error = git2::Error;
|
||||
|
||||
fn try_from(value: &git2::Branch<'_>) -> std::result::Result<Self, Self::Error> {
|
||||
if value.get().is_remote() {
|
||||
return Err(git2::Error::from_str("not a local branch"));
|
||||
}
|
||||
let name = String::from_utf8(value.name_bytes()?.to_vec())
|
||||
.map_err(|e| git2::Error::from_str(&e.to_string()))?;
|
||||
match value.upstream() {
|
||||
Ok(upstream) => {
|
||||
let remote_branch_name = RemoteName::try_from(&upstream)?;
|
||||
Ok(Self {
|
||||
branch: name,
|
||||
remote: Some(remote_branch_name),
|
||||
})
|
||||
}
|
||||
Err(error) => {
|
||||
if error.code() == git2::ErrorCode::NotFound {
|
||||
Ok(Self {
|
||||
branch: name,
|
||||
remote: None,
|
||||
})
|
||||
} else {
|
||||
Err(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Name {
|
||||
Remote(RemoteName),
|
||||
Local(LocalName),
|
||||
}
|
||||
|
||||
impl TryFrom<&git2::Branch<'_>> for Name {
|
||||
type Error = git2::Error;
|
||||
|
||||
fn try_from(value: &git2::Branch<'_>) -> std::result::Result<Self, Self::Error> {
|
||||
if value.get().is_remote() {
|
||||
Ok(Self::Remote(RemoteName::try_from(value)?))
|
||||
} else {
|
||||
Ok(Self::Local(LocalName::try_from(value)?))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
pub mod activity;
|
||||
pub mod conflicts;
|
||||
pub mod diff;
|
||||
pub mod branch;
|
||||
mod repository;
|
||||
|
||||
pub use repository::{Error, FileStatus, Repository};
|
||||
|
@ -8,6 +8,8 @@ use walkdir::WalkDir;
|
||||
|
||||
use crate::{project_repository::activity, projects, reader};
|
||||
|
||||
use super::branch;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
@ -218,30 +220,28 @@ impl<'repository> Repository<'repository> {
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
pub fn git_branches(&self) -> Result<Vec<String>> {
|
||||
let mut branches = vec![];
|
||||
for branch in self
|
||||
.git_repository
|
||||
pub fn git_branches(&self) -> Result<Vec<branch::LocalName>> {
|
||||
self.git_repository
|
||||
.branches(Some(git2::BranchType::Local))?
|
||||
{
|
||||
let (branch, _) = branch?;
|
||||
let name = branch.name()?.unwrap().to_string();
|
||||
branches.push(name);
|
||||
}
|
||||
Ok(branches)
|
||||
.flatten()
|
||||
.map(|(branch, _)| branch)
|
||||
.map(|branch| {
|
||||
branch::LocalName::try_from(&branch)
|
||||
.context("failed to convert branch to local name")
|
||||
})
|
||||
.collect::<Result<Vec<branch::LocalName>>>()
|
||||
}
|
||||
|
||||
pub fn git_remote_branches(&self) -> Result<Vec<String>> {
|
||||
let mut branches = vec![];
|
||||
for branch in self
|
||||
.git_repository
|
||||
pub fn git_remote_branches(&self) -> Result<Vec<branch::RemoteName>> {
|
||||
self.git_repository
|
||||
.branches(Some(git2::BranchType::Remote))?
|
||||
{
|
||||
let (branch, _) = branch?;
|
||||
let name = branch.name()?.unwrap().to_string();
|
||||
branches.push(name);
|
||||
}
|
||||
Ok(branches)
|
||||
.flatten()
|
||||
.map(|(branch, _)| branch)
|
||||
.map(|branch| {
|
||||
branch::RemoteName::try_from(&branch)
|
||||
.context("failed to convert branch to remote name")
|
||||
})
|
||||
.collect::<Result<Vec<branch::RemoteName>>>()
|
||||
}
|
||||
|
||||
// returns a list of commit oids from the first oid to the second oid
|
||||
|
Loading…
Reference in New Issue
Block a user