fix: themes are now not saved in installed pkg db
This commit is contained in:
@@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
||||
- Added commit hash based install/update for security reasons.
|
||||
- `install.sh` file for easy install in Linux.
|
||||
|
||||
### Fxied
|
||||
|
||||
- Themes being saved in eiipm installed package database.
|
||||
|
||||
## [0.3.0] - 2025-08-22
|
||||
|
||||
### Added
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
//! Working with git2 API's
|
||||
|
||||
use crate::other::confirm_action::confirm;
|
||||
use git2::{Cred, Error, FetchOptions, RemoteCallbacks, Repository, build::RepoBuilder};
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn clone_https(repo_url: &str, path: &Path, depth: Option<u32>) -> Result<Repository, Error> {
|
||||
let callbacks = RemoteCallbacks::new();
|
||||
|
||||
// Set up fetch options
|
||||
let mut fetch_options = FetchOptions::new();
|
||||
fetch_options.remote_callbacks(callbacks);
|
||||
|
||||
// Apply shallow clone if depth is specified
|
||||
if let Some(d) = depth {
|
||||
fetch_options.depth(d as i32);
|
||||
}
|
||||
|
||||
// Use RepoBuilder directly
|
||||
let mut builder = RepoBuilder::new();
|
||||
builder.fetch_options(fetch_options);
|
||||
|
||||
let repo = builder.clone(repo_url, path)?;
|
||||
Ok(repo)
|
||||
}
|
||||
|
||||
pub fn pull_https(repo: &Repository) -> Result<(), Error> {
|
||||
let head_ref = repo.head()?;
|
||||
let branch_name = head_ref
|
||||
.shorthand()
|
||||
.ok_or_else(|| Error::from_str("Invalid branch"))?;
|
||||
|
||||
// Fetch remote branch
|
||||
let callbacks = RemoteCallbacks::new();
|
||||
let mut fetch_options = FetchOptions::new();
|
||||
fetch_options.remote_callbacks(callbacks);
|
||||
|
||||
let mut remote = repo.find_remote("origin")?;
|
||||
remote.fetch(&[branch_name], Some(&mut fetch_options), None)?;
|
||||
|
||||
// Find fetched commit
|
||||
let fetch_ref = repo.find_reference(&format!("refs/remotes/origin/{}", branch_name))?;
|
||||
let fetch_commit = repo.reference_to_annotated_commit(&fetch_ref)?;
|
||||
|
||||
// Merge analysis
|
||||
let analysis = repo.merge_analysis(&[&fetch_commit])?;
|
||||
|
||||
if analysis.0.is_fast_forward() {
|
||||
// Fast-forward
|
||||
let mut ref_to_update = repo.find_reference(head_ref.name().unwrap())?;
|
||||
ref_to_update.set_target(fetch_commit.id(), "Fast-forward")?;
|
||||
repo.set_head(head_ref.name().unwrap())?;
|
||||
repo.checkout_head(Some(git2::build::CheckoutBuilder::default().force()))?;
|
||||
log::info!("Fast-forward merge completed");
|
||||
} else {
|
||||
// Real merge
|
||||
log::info!("Fast-forward not possible, performing merge...");
|
||||
|
||||
let head_commit = repo.reference_to_annotated_commit(&head_ref)?;
|
||||
let head_tree = repo.find_commit(head_commit.id())?.tree()?;
|
||||
let fetch_tree = repo.find_commit(fetch_commit.id())?.tree()?;
|
||||
|
||||
let ancestor_commit = repo
|
||||
.merge_base(head_commit.id(), fetch_commit.id())
|
||||
.and_then(|oid| repo.find_commit(oid))?;
|
||||
let ancestor_tree = ancestor_commit.tree()?;
|
||||
|
||||
let mut idx = repo.merge_trees(&ancestor_tree, &head_tree, &fetch_tree, None)?;
|
||||
if idx.has_conflicts() {
|
||||
return Err(Error::from_str(
|
||||
"Merge conflicts detected. Please resolve manually.",
|
||||
));
|
||||
}
|
||||
|
||||
// Write the merged tree
|
||||
let result_tree_id = idx.write_tree_to(repo)?;
|
||||
let result_tree = repo.find_tree(result_tree_id)?;
|
||||
|
||||
// Create merge commit
|
||||
let sig = repo.signature()?;
|
||||
let head_commit_obj = repo.find_commit(head_commit.id())?;
|
||||
let fetch_commit_obj = repo.find_commit(fetch_commit.id())?;
|
||||
|
||||
repo.commit(
|
||||
Some(head_ref.name().unwrap()), // update current branch
|
||||
&sig,
|
||||
&sig,
|
||||
"Merge commit from pull",
|
||||
&result_tree,
|
||||
&[&head_commit_obj, &fetch_commit_obj],
|
||||
)?;
|
||||
|
||||
// Checkout updated HEAD
|
||||
repo.checkout_head(Some(git2::build::CheckoutBuilder::default().force()))?;
|
||||
log::info!("Merge completed successfully");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pull_but_reclone_on_fail(
|
||||
repo_url: &str,
|
||||
repo_path: &Path,
|
||||
depth: Option<u32>,
|
||||
) -> Result<Repository, Error> {
|
||||
// Try opening the repo if it exists
|
||||
if let Ok(repo) = Repository::open(repo_path) {
|
||||
// Try to pull
|
||||
match pull_https(&repo) {
|
||||
Ok(_) => return Ok(repo),
|
||||
Err(err) => {
|
||||
log::warn!("Pull failed: {}.", err);
|
||||
|
||||
let user_confirm = confirm("Failed to update cache (outdated). Remove and retry?");
|
||||
|
||||
let home_dir = dirs::home_dir()
|
||||
.ok_or_else(|| Error::from_str("Failed to get home directory"))?;
|
||||
let cache_root = home_dir.join(".eiipm/cache");
|
||||
|
||||
if user_confirm {
|
||||
if !repo_path.starts_with(cache_root.as_path()) {
|
||||
return Err(Error::from_str(&format!(
|
||||
"Refusing to delete outside cache: {}",
|
||||
repo_path.display()
|
||||
)));
|
||||
}
|
||||
|
||||
fs::remove_dir_all(repo_path)
|
||||
.map_err(|e| Error::from_str(&format!("Failed to remove dir: {}", e)))?;
|
||||
} else {
|
||||
// user refused, so just return the repo as-is
|
||||
return Ok(repo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Either repo didn't exist or we removed it, so clone fresh
|
||||
clone_https(repo_url, repo_path, depth)
|
||||
}
|
||||
|
||||
/// Checks if the current branch is behind its upstream.
|
||||
/// Returns `Ok(true)` if the upstream has commits the local branch doesn't have.
|
||||
pub fn is_upstream_ahead(repo_path: &str) -> Result<bool, Error> {
|
||||
let repo = Repository::open(repo_path)?;
|
||||
|
||||
// Get the current branch
|
||||
let head_ref = repo.head()?;
|
||||
let branch_name = head_ref
|
||||
.shorthand()
|
||||
.ok_or_else(|| Error::from_str("Invalid branch name"))?;
|
||||
|
||||
// Set up fetch options with authentication callbacks
|
||||
let mut callbacks = RemoteCallbacks::new();
|
||||
callbacks.credentials(|_url, username_from_url, _allowed_types| {
|
||||
Cred::ssh_key_from_agent(username_from_url.unwrap_or("git"))
|
||||
});
|
||||
let mut fetch_options = FetchOptions::new();
|
||||
fetch_options.remote_callbacks(callbacks);
|
||||
|
||||
// Fetch from origin
|
||||
let mut remote = repo.find_remote("origin")?;
|
||||
remote.fetch(&[branch_name], Some(&mut fetch_options), None)?;
|
||||
|
||||
// Resolve upstream
|
||||
let local_branch = repo.find_branch(branch_name, git2::BranchType::Local)?;
|
||||
let upstream_branch = local_branch.upstream()?;
|
||||
|
||||
let local_oid = local_branch
|
||||
.get()
|
||||
.target()
|
||||
.ok_or_else(|| Error::from_str("Local branch has no commit"))?;
|
||||
let upstream_oid = upstream_branch
|
||||
.get()
|
||||
.target()
|
||||
.ok_or_else(|| Error::from_str("Upstream branch has no commit"))?;
|
||||
|
||||
let (_ahead, behind) = repo.graph_ahead_behind(local_oid, upstream_oid)?;
|
||||
|
||||
Ok(behind > 0)
|
||||
}
|
||||
@@ -6,7 +6,7 @@ Eiipm is a fast and eligant package manager made in rust for [Ewwii](https://git
|
||||
|
||||
You can install **eiipm** using the same [methods we discussed](https://ewwii-sh.github.io/ewwii/installation.html) of in Ewwii:
|
||||
|
||||
#### 1. From installer (fastest)
|
||||
#### 1. From installer (Linux Only)
|
||||
|
||||
```bash
|
||||
curl -sSL https://raw.githubusercontent.com/Ewwii-sh/eiipm/main/install.sh -o install.sh
|
||||
@@ -24,7 +24,15 @@ eiipm --version
|
||||
>
|
||||
> If eiipm doesn't work after the installation, make sure that `/usr/local/bin` is in path.
|
||||
|
||||
#### 2. From source
|
||||
#### 2. From GitHub releases (Linux Only)
|
||||
|
||||
If you are on Linux, then you can install the pre-built binary from [eiipm GitHub releases](https://github.com/Ewwii-sh/eiipm/releases/latest).
|
||||
|
||||
- Go to the latest GitHub release. [Click Me!](https://github.com/Ewwii-sh/eiipm/releases/latest)
|
||||
- Install the binary (that is named `eiipm`) from assets section.
|
||||
- Voila! You now have eiipm installed!
|
||||
|
||||
#### 3. From source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Ewwii-sh/eiipm
|
||||
@@ -34,7 +42,7 @@ cargo build --release
|
||||
|
||||
This will generate the `eiipm` binary in `target/release`.
|
||||
|
||||
#### 3. Using Cargo
|
||||
#### 4. Using Cargo
|
||||
|
||||
```bash
|
||||
cargo install --git https://github.com/Ewwii-sh/eiipm
|
||||
|
||||
@@ -113,22 +113,24 @@ pub fn install_package(package_name: &str) -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
// Update DB
|
||||
let mut db = load_db()?;
|
||||
db.packages.insert(
|
||||
meta.name.clone(),
|
||||
InstalledPackage {
|
||||
repo_fs_path: repo_fs_path.to_string_lossy().to_string(),
|
||||
installed_files: installed_files,
|
||||
copy_files: meta.files.clone(),
|
||||
pkg_type: meta.pkg_type.clone(),
|
||||
upstream_src: meta.src.clone(),
|
||||
installed_hash: meta.commit_hash.clone(),
|
||||
manifest_url: raw_manifest_url,
|
||||
build_command: meta.build.clone(),
|
||||
},
|
||||
);
|
||||
save_db(&db)?;
|
||||
// Update DB if its not a theme
|
||||
if !(meta.pkg_type == "theme") {
|
||||
let mut db = load_db()?;
|
||||
db.packages.insert(
|
||||
meta.name.clone(),
|
||||
InstalledPackage {
|
||||
repo_fs_path: repo_fs_path.to_string_lossy().to_string(),
|
||||
installed_files: installed_files,
|
||||
copy_files: meta.files.clone(),
|
||||
pkg_type: meta.pkg_type.clone(),
|
||||
upstream_src: meta.src.clone(),
|
||||
installed_hash: meta.commit_hash.clone(),
|
||||
manifest_url: raw_manifest_url,
|
||||
build_command: meta.build.clone(),
|
||||
},
|
||||
);
|
||||
save_db(&db)?;
|
||||
}
|
||||
|
||||
info!(
|
||||
"Installation complete for '{}'",
|
||||
|
||||
@@ -21,6 +21,8 @@ pub fn update_package(package_name: &Option<String>) -> Result<(), Box<dyn Error
|
||||
pkg.pkg_type
|
||||
);
|
||||
|
||||
// there is no way that it can be a theme
|
||||
// but... what if?
|
||||
if pkg.pkg_type == "theme" {
|
||||
info!("Skipping theme package '{}'", name.yellow().bold());
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user