Skip to content

Commit

Permalink
Add command for remotes
Browse files Browse the repository at this point in the history
  • Loading branch information
svenslaggare committed Jan 25, 2025
1 parent 1e39471 commit 67a9e49
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 30 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Searching for properties of notes (such as tags or creation date) can be done us
Content based searches "grep" can be done with the `gitnotes grep` command. It is also possible to search for past content using the `--history` argument where a git commit spec is used.

### Converting note to PDF
Notes can be converted to PDF's with `gitnotes conver <note> <destination>`.
Notes can be converted to PDF's with `gitnotes convert <note> <destination>`.

Under the hood, `pandoc` is used. See https://www.baeldung.com/linux/pdf-markdown-conversion for how to install.

Expand All @@ -103,4 +103,7 @@ Any editor can be used to edit notes. The editors that are most preferred are th
The path used is _virtual_ in the sense that it doesn't affect the actual folder structure (the file path is just a metadata property of the note). All notes also have a numeric ID that can be used to refer to the note instead of the (virtual) path.

### Synchronization
Synchronization can be done by adding a git remote (manually) and then using the `gitnotes sync` command.
Synchronization can be done by adding a git remote and then using the `gitnotes sync` command.

#### Adding remote
Add a remote (SSH only supported) using `gitnotes remote add origin <URL>`.
110 changes: 83 additions & 27 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,30 @@ impl App {
self.execute_commands(vec![Command::Commit])?;
self.auto_commit = true;
}
InputCommand::Remote { command } => {
match command {
InputCommandRemote::List { .. } => {
let repository = self.repository.borrow();
println!("Remotes:");
for remote in repository.remotes()?.iter() {
if let Some(remote) = remote {
let remote = repository.find_remote(&remote).map_err(|_| RemoteNotFound(remote.to_owned()))?;
println!("{}: {}", remote.name().unwrap_or("N/A"), remote.url().unwrap_or("N/A"));
}
}
}
InputCommandRemote::Add { name, url } => {
let repository = self.repository.borrow();
repository.remote_set_url(&name, &url)?;
println!("Added remote '{}.", name);
}
InputCommandRemote::Remove { name } => {
let repository = self.repository.borrow();
repository.remote_delete(&name).map_err(|_| RemoteNotFound(name.to_owned()))?;
println!("Removed remote '{}.", name);
}
}
}
InputCommand::Synchronize { branch, remote, no_pull, no_push } => {
let branch = branch.unwrap_or_else(|| self.config.sync_default_branch.clone());
let remote = remote.unwrap_or_else(|| self.config.sync_default_remote.clone());
Expand All @@ -235,10 +259,7 @@ impl App {

let repository = self.repository.borrow();

let branch_ref = repository.find_branch(&branch, BranchType::Local).map_err(|_| BranchNotFound(branch.clone()))?;
let branch_ref = branch_ref.into_reference();
let branch_ref = branch_ref.name().ok_or_else(|| InternalError("Failed to unwrap branch ref".to_owned()))?;

let branch_ref = git_helpers::find_branch_ref(&repository, &branch)?;
let mut remote = repository.find_remote(&remote).map_err(|_| RemoteNotFound(remote.clone()))?;

if pull {
Expand All @@ -249,7 +270,7 @@ impl App {
callbacks.credentials(git_helpers::create_ssh_credentials());
fetch_options.remote_callbacks(callbacks);

remote.fetch(&[branch_ref], Some(&mut fetch_options), None)?;
remote.fetch(&[&branch_ref], Some(&mut fetch_options), None)?;
let fetch_head = repository.find_reference("FETCH_HEAD")?;
let fetch_commit = repository.reference_to_annotated_commit(&fetch_head)?;
git_helpers::merge(&repository, &branch, fetch_commit)?;
Expand All @@ -263,7 +284,7 @@ impl App {
callbacks.credentials(git_helpers::create_ssh_credentials());
push_options.remote_callbacks(callbacks);

remote.push(&[branch_ref], Some(&mut push_options))?;
remote.push(&[&branch_ref], Some(&mut push_options))?;
}
}
InputCommand::PrintContent { path, history, only_code, only_output } => {
Expand Down Expand Up @@ -307,26 +328,8 @@ impl App {
open::that(&self.config.repository)?;
}
InputCommand::Finder { interactive, command } => {
let query = match command {
InputCommandFinder::Tag { tags } => {
FindQuery::Tags(tags)
}
InputCommandFinder::Name { name } => {
FindQuery::Path(name)
}
InputCommandFinder::Id { id } => {
FindQuery::Id(id)
}
InputCommandFinder::Created { parts } => {
FindQuery::Created(parts)
}
InputCommandFinder::Updated { parts } => {
FindQuery::LastUpdated(parts)
}
};

let finder = Finder::new(self.note_metadata_storage()?)?;
let results = finder.find(&query)?;
let results = finder.find(&command.query())?;
print_note_metadata_results(&results);

if let Some(command) = interactive {
Expand Down Expand Up @@ -391,8 +394,14 @@ impl App {
}
InputCommand::Info { path, only_file_system_path } => {
self.note_metadata_storage()?;
let note_metadata = self.note_metadata_storage_ref()?.get(&path).ok_or_else(|| QueryingError::NoteNotFound(path.to_str().unwrap().to_owned()))?;
let file_system_path = NoteMetadataStorage::get_note_storage_path(&self.config.repository, &note_metadata.id).1.to_str().unwrap().to_owned();
let note_metadata = self.note_metadata_storage_ref()?
.get(&path)
.ok_or_else(|| QueryingError::NoteNotFound(path.to_str().unwrap().to_owned()))?;

let file_system_path = NoteMetadataStorage::get_note_storage_path(
&self.config.repository,
&note_metadata.id
).1.to_str().unwrap().to_owned();

if !only_file_system_path {
println!("Id: {}", note_metadata.id);
Expand Down Expand Up @@ -806,6 +815,11 @@ pub enum InputCommand {
/// Commits the started transaction. If no changes have been made, a commit is not created (interactive mode only).
Commit {

},
/// Manages remote git instances
Remote {
#[structopt(subcommand)]
command: InputCommandRemote
},
/// Synchronizes the notes with a remote git instance
#[structopt(name="sync")]
Expand Down Expand Up @@ -979,6 +993,48 @@ pub enum InputCommandFinder {
}
}

impl InputCommandFinder {
pub fn query(self) -> FindQuery {
match self {
InputCommandFinder::Tag { tags } => {
FindQuery::Tags(tags)
}
InputCommandFinder::Name { name } => {
FindQuery::Path(name)
}
InputCommandFinder::Id { id } => {
FindQuery::Id(id)
}
InputCommandFinder::Created { parts } => {
FindQuery::Created(parts)
}
InputCommandFinder::Updated { parts } => {
FindQuery::LastUpdated(parts)
}
}
}
}

#[derive(Debug, StructOpt)]
pub enum InputCommandRemote {
/// Lists the existing remotes
List {

},
/// Adds a new remote
Add {
/// The name of the remote
name: String,
/// The URL of the remote
url: String
},
/// Removes an existing remote
Remove {
/// The name of the remoote
name: String
}
}

pub type AppResult<T> = Result<T, AppError>;

#[derive(Error, Debug)]
Expand Down
10 changes: 9 additions & 1 deletion src/git_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
use git2::{Cred, CredentialType, Repository};
use git2::{BranchType, Cred, CredentialType, Repository};
use crate::command::CommandError;

pub fn find_branch_ref(repository: &Repository, branch: &str) -> Result<String, CommandError> {
let branch_ref = repository.find_branch(&branch, BranchType::Local).map_err(|_| CommandError::BranchNotFound(branch.to_owned()))?;
let branch_ref = branch_ref.into_reference();
let branch_ref = branch_ref.name().ok_or_else(|| CommandError::InternalError("Failed to unwrap branch ref".to_owned()))?;
Ok(branch_ref.to_string())
}

pub fn create_ssh_credentials() -> impl FnMut(&str, Option<&str>, CredentialType) -> Result<Cred, git2::Error> {
|_url, username_from_url, _allowed_types| {
Expand Down

0 comments on commit 67a9e49

Please sign in to comment.