mirror of
https://github.com/extrawurst/gitui.git
synced 2024-11-22 02:12:58 +03:00
parent
08f6735d99
commit
7d1e3643b1
2
.github/workflows/cd.yml
vendored
2
.github/workflows/cd.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -15,7 +15,6 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
rust: [nightly, stable]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.rust == 'nightly' }}
|
||||
|
||||
@ -54,14 +53,13 @@ jobs:
|
||||
build-linux-musl:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@master
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
target: x86_64-unknown-linux-musl
|
||||
|
||||
- name: Setup MUSL
|
||||
run: |
|
||||
sudo apt-get -qq install musl-tools
|
||||
@ -73,6 +71,9 @@ jobs:
|
||||
run: |
|
||||
make build-linux-musl-release
|
||||
./target/x86_64-unknown-linux-musl/release/gitui --version
|
||||
- name: Test
|
||||
run: |
|
||||
make test-linux-musl
|
||||
|
||||
rustfmt:
|
||||
name: Rustfmt
|
||||
|
47
Cargo.lock
generated
47
Cargo.lock
generated
@ -414,6 +414,8 @@ dependencies = [
|
||||
"libc",
|
||||
"libgit2-sys",
|
||||
"log",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"url",
|
||||
]
|
||||
|
||||
@ -552,10 +554,26 @@ checksum = "0100ae90655025134424939f1f60e27e879460d451dff6afedde4f8226cbebfc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libssh2-sys",
|
||||
"libz-sys",
|
||||
"openssl-sys",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libssh2-sys"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"openssl-sys",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.1.0"
|
||||
@ -785,6 +803,35 @@ version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-src"
|
||||
version = "111.10.2+1.1.1g"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a287fdb22e32b5b60624d4a5a7a02dbe82777f730ec0dbc42a0554326fef5a70"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
"libc",
|
||||
"openssl-src",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.10.2"
|
||||
|
3
Makefile
3
Makefile
@ -31,6 +31,9 @@ build-linux-musl-debug:
|
||||
build-linux-musl-release:
|
||||
cargo build --release --target=x86_64-unknown-linux-musl --no-default-features
|
||||
|
||||
test-linux-musl:
|
||||
cargo test --workspace --target=x86_64-unknown-linux-musl --no-default-features
|
||||
|
||||
test:
|
||||
cargo test --workspace
|
||||
|
||||
|
@ -59,4 +59,5 @@
|
||||
commit_amend: ( code: Char('A'), modifiers: ( bits: 0,),),
|
||||
copy: ( code: Char('y'), modifiers: ( bits: 0,),),
|
||||
create_branch: ( code: Char('b'), modifiers: ( bits: 0,),),
|
||||
push: ( code: Char('p'), modifiers: ( bits: 0,),),
|
||||
)
|
||||
|
@ -13,7 +13,7 @@ keywords = ["git"]
|
||||
|
||||
[dependencies]
|
||||
scopetime = { path = "../scopetime", version = "0.1" }
|
||||
git2 = { version = "0.13.10", default-features = false }
|
||||
git2 = { version = "0.13", features = ["vendored-openssl"] }
|
||||
rayon-core = "1.8"
|
||||
crossbeam-channel = "0.4"
|
||||
log = "0.4"
|
||||
|
@ -32,6 +32,11 @@ impl BranchName {
|
||||
self.fetch(current_head)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn last(&self) -> Option<String> {
|
||||
self.last_result.as_ref().map(|last| last.1.clone())
|
||||
}
|
||||
|
||||
fn fetch(&mut self, head: Head) -> Result<String> {
|
||||
let name = sync::get_branch_name(self.repo_path.as_str())?;
|
||||
self.last_result = Some((head, name.clone()));
|
||||
|
@ -10,6 +10,7 @@ mod hooks;
|
||||
mod hunks;
|
||||
mod ignore;
|
||||
mod logwalker;
|
||||
mod remotes;
|
||||
mod reset;
|
||||
mod stash;
|
||||
pub mod status;
|
||||
@ -29,6 +30,9 @@ pub use hooks::{hooks_commit_msg, hooks_post_commit, HookResult};
|
||||
pub use hunks::{reset_hunk, stage_hunk, unstage_hunk};
|
||||
pub use ignore::add_to_ignore;
|
||||
pub use logwalker::LogWalker;
|
||||
pub use remotes::{
|
||||
fetch_origin, get_remotes, push_origin, remote_push_master,
|
||||
};
|
||||
pub use reset::{reset_stage, reset_workdir};
|
||||
pub use stash::{get_stashes, stash_apply, stash_drop, stash_save};
|
||||
pub use tags::{get_tags, CommitTags, Tags};
|
||||
|
103
asyncgit/src/sync/remotes.rs
Normal file
103
asyncgit/src/sync/remotes.rs
Normal file
@ -0,0 +1,103 @@
|
||||
//!
|
||||
|
||||
use crate::{error::Result, sync::utils};
|
||||
use git2::{Cred, FetchOptions, PushOptions, RemoteCallbacks};
|
||||
use scopetime::scope_time;
|
||||
|
||||
///
|
||||
pub fn get_remotes(repo_path: &str) -> Result<Vec<String>> {
|
||||
scope_time!("get_remotes");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
let remotes = repo.remotes()?;
|
||||
let remotes: Vec<String> =
|
||||
remotes.iter().filter_map(|s| s).map(String::from).collect();
|
||||
|
||||
Ok(remotes)
|
||||
}
|
||||
|
||||
///
|
||||
pub fn remote_push_master(repo_path: &str) -> Result<()> {
|
||||
scope_time!("remote_push_master");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
let mut remote = repo.find_remote("origin")?;
|
||||
|
||||
remote.push(&["refs/heads/master"], None)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn fetch_origin(repo_path: &str, branch: &str) -> Result<usize> {
|
||||
scope_time!("remote_fetch_master");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
let mut remote = repo.find_remote("origin")?;
|
||||
|
||||
let mut options = FetchOptions::new();
|
||||
options.remote_callbacks(remote_callbacks());
|
||||
|
||||
remote.fetch(&[branch], Some(&mut options), None)?;
|
||||
|
||||
Ok(remote.stats().received_bytes())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn push_origin(repo_path: &str, branch: &str) -> Result<()> {
|
||||
scope_time!("push_origin");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
let mut remote = repo.find_remote("origin")?;
|
||||
|
||||
let mut options = PushOptions::new();
|
||||
options.remote_callbacks(remote_callbacks());
|
||||
|
||||
remote.push(&[branch], Some(&mut options))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remote_callbacks<'a>() -> RemoteCallbacks<'a> {
|
||||
let mut callbacks = RemoteCallbacks::new();
|
||||
callbacks.credentials(|url, username_from_url, allowed_types| {
|
||||
log::debug!(
|
||||
"creds: '{}' {:?} ({:?})",
|
||||
url,
|
||||
username_from_url,
|
||||
allowed_types
|
||||
);
|
||||
|
||||
Cred::ssh_key_from_agent(
|
||||
username_from_url.expect("username not found"),
|
||||
)
|
||||
});
|
||||
|
||||
callbacks
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::sync::tests::debug_cmd_print;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn test_smoke() {
|
||||
let td = TempDir::new().unwrap();
|
||||
|
||||
debug_cmd_print(
|
||||
td.path().as_os_str().to_str().unwrap(),
|
||||
"git clone https://github.com/extrawurst/brewdump.git",
|
||||
);
|
||||
|
||||
let repo_path = td.path().join("brewdump");
|
||||
let repo_path = repo_path.as_os_str().to_str().unwrap();
|
||||
|
||||
let remotes = get_remotes(repo_path).unwrap();
|
||||
|
||||
assert_eq!(remotes, vec![String::from("origin")]);
|
||||
|
||||
fetch_origin(repo_path, "master").unwrap();
|
||||
}
|
||||
}
|
@ -256,7 +256,7 @@ impl App {
|
||||
let msg =
|
||||
format!("failed to launch editor:\n{}", e);
|
||||
log::error!("{}", msg.as_str());
|
||||
self.msg.show_msg(msg.as_str())?;
|
||||
self.msg.show_error(msg.as_str())?;
|
||||
}
|
||||
|
||||
self.requires_redraw.set(true);
|
||||
@ -454,7 +454,12 @@ impl App {
|
||||
flags.insert(NeedsUpdate::COMMANDS);
|
||||
}
|
||||
InternalEvent::ShowErrorMsg(msg) => {
|
||||
self.msg.show_msg(msg.as_str())?;
|
||||
self.msg.show_error(msg.as_str())?;
|
||||
flags
|
||||
.insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS);
|
||||
}
|
||||
InternalEvent::ShowInfoMsg(msg) => {
|
||||
self.msg.show_info(msg.as_str())?;
|
||||
flags
|
||||
.insert(NeedsUpdate::ALL | NeedsUpdate::COMMANDS);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ pub fn copy_string(_string: String) -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub fn is_supported() -> bool {
|
||||
pub const fn is_supported() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -64,6 +64,11 @@ impl ChangesComponent {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn branch_name(&self) -> Option<String> {
|
||||
self.branch_name.last()
|
||||
}
|
||||
|
||||
///
|
||||
pub fn set_items(&mut self, list: &[StatusItem]) -> Result<()> {
|
||||
self.files.update(list)?;
|
||||
|
@ -14,6 +14,7 @@ use tui::{
|
||||
use ui::style::SharedTheme;
|
||||
|
||||
pub struct MsgComponent {
|
||||
title: String,
|
||||
msg: String,
|
||||
visible: bool,
|
||||
theme: SharedTheme,
|
||||
@ -39,9 +40,7 @@ impl DrawableComponent for MsgComponent {
|
||||
Paragraph::new(txt.iter())
|
||||
.block(
|
||||
Block::default()
|
||||
.title(&strings::msg_title_error(
|
||||
&self.key_config,
|
||||
))
|
||||
.title(self.title.as_str())
|
||||
.title_style(self.theme.text_danger())
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Thick),
|
||||
@ -104,14 +103,26 @@ impl MsgComponent {
|
||||
key_config: SharedKeyConfig,
|
||||
) -> Self {
|
||||
Self {
|
||||
title: String::new(),
|
||||
msg: String::new(),
|
||||
visible: false,
|
||||
theme,
|
||||
key_config,
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn show_msg(&mut self, msg: &str) -> Result<()> {
|
||||
pub fn show_error(&mut self, msg: &str) -> Result<()> {
|
||||
self.title = strings::msg_title_error(&self.key_config);
|
||||
self.msg = msg.to_string();
|
||||
self.show()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
///
|
||||
pub fn show_info(&mut self, msg: &str) -> Result<()> {
|
||||
self.title = strings::msg_title_info(&self.key_config);
|
||||
self.msg = msg.to_string();
|
||||
self.show()?;
|
||||
|
||||
|
@ -60,6 +60,7 @@ pub struct KeyConfig {
|
||||
pub commit_amend: KeyEvent,
|
||||
pub copy: KeyEvent,
|
||||
pub create_branch: KeyEvent,
|
||||
pub push: KeyEvent,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
@ -109,6 +110,7 @@ impl Default for KeyConfig {
|
||||
commit_amend: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::CONTROL},
|
||||
copy: KeyEvent { code: KeyCode::Char('y'), modifiers: KeyModifiers::empty()},
|
||||
create_branch: KeyEvent { code: KeyCode::Char('b'), modifiers: KeyModifiers::empty()},
|
||||
push: KeyEvent { code: KeyCode::Char('p'), modifiers: KeyModifiers::empty()},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ pub enum InternalEvent {
|
||||
///
|
||||
ShowErrorMsg(String),
|
||||
///
|
||||
ShowInfoMsg(String),
|
||||
///
|
||||
Update(NeedsUpdate),
|
||||
/// open commit msg input
|
||||
OpenCommit,
|
||||
|
@ -40,6 +40,9 @@ pub fn msg_opening_editor(_key_config: &SharedKeyConfig) -> String {
|
||||
pub fn msg_title_error(_key_config: &SharedKeyConfig) -> String {
|
||||
"Error".to_string()
|
||||
}
|
||||
pub fn msg_title_info(_key_config: &SharedKeyConfig) -> String {
|
||||
"Info".to_string()
|
||||
}
|
||||
pub fn commit_title(_key_config: &SharedKeyConfig) -> String {
|
||||
"Commit".to_string()
|
||||
}
|
||||
@ -596,4 +599,11 @@ pub mod commands {
|
||||
CMD_GROUP_GENERAL,
|
||||
)
|
||||
}
|
||||
pub fn status_push(key_config: &SharedKeyConfig) -> CommandText {
|
||||
CommandText::new(
|
||||
format!("Push [{}]", get_hint(key_config.push),),
|
||||
"push to origin",
|
||||
CMD_GROUP_GENERAL,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -323,6 +323,24 @@ impl Status {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&self) {
|
||||
if let Some(branch) = self.index_wd.branch_name() {
|
||||
let branch = format!("refs/heads/{}", branch);
|
||||
if let Err(e) = sync::push_origin(CWD, branch.as_str()) {
|
||||
self.queue.borrow_mut().push_back(
|
||||
InternalEvent::ShowErrorMsg(format!(
|
||||
"push failed:\n{}",
|
||||
e
|
||||
)),
|
||||
);
|
||||
} else {
|
||||
self.queue.borrow_mut().push_back(
|
||||
InternalEvent::ShowInfoMsg("pushed".to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Status {
|
||||
@ -369,6 +387,11 @@ impl Component for Status {
|
||||
true,
|
||||
true,
|
||||
));
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::status_push(&self.key_config),
|
||||
self.index_wd.branch_name().is_some(),
|
||||
true,
|
||||
));
|
||||
|
||||
out.push(
|
||||
CommandInfo::new(
|
||||
@ -451,6 +474,9 @@ impl Component for Status {
|
||||
.borrow_mut()
|
||||
.push_back(InternalEvent::CreateBranch);
|
||||
Ok(true)
|
||||
} else if k == self.key_config.push {
|
||||
self.push();
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user