Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pkgbuild): add PKGBUILD editing functionality #1288

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ signal-hook = "0.3.17"
once_cell = "1.20.2"
bitflags = "2.6.0"
toml = { version = "0.8.19", features = ["preserve_order"] }
which = "7.0.0"
shell-words = "1.1.0"

[profile.release]
codegen-units = 1
Expand Down
7 changes: 3 additions & 4 deletions src/command_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ impl Config {
Arg::Long("fm") => self.fm = Some(value?.to_string()),
Arg::Long("pager") => self.pager_cmd = Some(value?.to_string()),
Arg::Long("config") => self.pacman_conf = Some(value?.to_string()),

Arg::Long("editor") => self.editor = Some(value?.to_string()),
Arg::Long("editorflags") => self.editor_flags.extend(split_whitespace(value?)),
Arg::Long("editmenu") => self.edit_menu = true,
Arg::Long("builddir") | Arg::Long("clonedir") => self.build_dir = value?.into(),
Arg::Long("develfile") => self.devel_path = value?.into(),
Arg::Long("makepkgconf") => self.makepkg_conf = Some(value?.to_string()),
Expand All @@ -198,11 +200,9 @@ impl Config {
Arg::Long("chrootpkgs") => self
.chroot_pkgs
.extend(value?.split(',').map(|s| s.to_string())),

Arg::Long("develsuffixes") => self.devel_suffixes = split_whitespace(value?),
Arg::Long("installdebug") => self.install_debug = true,
Arg::Long("noinstalldebug") => self.install_debug = false,

Arg::Long("completioninterval") => {
self.completion_interval = value?
.parse()
Expand Down Expand Up @@ -295,7 +295,6 @@ impl Config {
Arg::Long("list") | Arg::Short('l') => self.list = true,
Arg::Long("delete") | Arg::Short('d') => self.delete += 1,
Arg::Long("noinstall") => self.no_install = true,

Arg::Long("print") | Arg::Short('p') => self.print = true,
Arg::Long("newsonupgrade") => self.news_on_upgrade = true,
Arg::Long("nonewsonupgrade") => self.news_on_upgrade = false,
Expand Down
12 changes: 12 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,10 @@ pub struct Config {
pub ignore_devel_builder: GlobSetBuilder,
pub assume_installed: Vec<String>,

pub edit_menu: bool,
pub editor: Option<String>,
pub editor_flags: Vec<String>,

#[default(PkgbuildRepos::new(aur_fetch::Fetch::with_cache_dir("repo")))]
pub pkgbuild_repos: PkgbuildRepos,
}
Expand Down Expand Up @@ -1023,6 +1027,9 @@ then initialise it with:
"FileManagerFlags" => self.fm_flags.extend(split),
"ChrootFlags" => self.chroot_flags.extend(split),
"PreBuildCommand" => self.pre_build_command = Some(value),
"Editor" => self.editor = Some(value),
"EditorFlags" => self.editor_flags.extend(split),
"EditMenu" => self.edit_menu = true,
_ => eprintln!(
"{}",
tr!("error: unknown option '{}' in section [bin]", key)
Expand Down Expand Up @@ -1135,6 +1142,11 @@ then initialise it with:
self.mode |= word.parse()?;
}
}
"Editor" => self.editor = Some(value?),
"EditorFlags" => self
.editor_flags
.extend(value?.split_whitespace().map(|s| s.to_string())),
"EditMenu" => self.edit_menu = true,
_ => ok2 = false,
};

Expand Down
22 changes: 19 additions & 3 deletions src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::devel::{fetch_devel_info, load_devel_info, save_devel_info, DevelInfo
use crate::download::{self, Bases};
use crate::fmt::{print_indent, print_install, print_install_verbose};
use crate::keys::check_pgp_keys;
use crate::pkgbuild::PkgbuildRepo;
use crate::pkgbuild::{edit_pkgbuilds, PkgbuildRepo};
use crate::resolver::{flags, resolver};
use crate::upgrade::{get_upgrades, Upgrades};
use crate::util::{ask, repo_aur_pkgs, split_repo_aur_targets};
Expand Down Expand Up @@ -199,6 +199,7 @@ impl Installer {
bail!(tr!("could not find .SRCINFO for '{}'", base.package_base()));
}
}

Ok(())
}

Expand Down Expand Up @@ -1109,7 +1110,12 @@ impl Installer {
};

if !config.skip_review && actions.iter_aur_pkgs().next().is_some() {
if !ask(config, &tr!("Proceed to review?"), true) {
let msg = if config.edit_menu {
tr!("Proceed to edit and review?")
} else {
tr!("Proceed to review?")
};
if !ask(config, &msg, true) {
return Status::err(1);
}
} else if !ask(config, &tr!("Proceed with installation?"), true) {
Expand All @@ -1126,6 +1132,16 @@ impl Installer {
let bases = actions.iter_aur_pkgs().cloned().collect();
self.download_pkgbuilds(config, &bases).await?;

if config.edit_menu {
let paths: Vec<PathBuf> = bases
.bases
.iter()
.map(|base| config.build_dir.join(base.package_base()))
.collect();

edit_pkgbuilds(config, &paths)?;
}

for pkg in &actions.build {
match pkg {
Base::Aur(base) => {
Expand Down Expand Up @@ -1155,6 +1171,7 @@ impl Installer {
Base::Pkgbuild(_) => None,
})
.collect::<Vec<_>>();

review(config, &config.fetch, &pkgs)?;
}

Expand Down Expand Up @@ -1260,7 +1277,6 @@ fn print_warnings(config: &Config, cache: &Cache, actions: Option<&Actions>) {
if !config.mode.aur() && !config.mode.pkgbuild() {
return;
}

if config.args.has_arg("u", "sysupgrade") && config.mode.aur() {
let (_, mut pkgs) = repo_aur_pkgs(config);
pkgs.retain(|pkg| config.pkgbuild_repos.pkg(config, pkg.name()).is_none());
Expand Down
64 changes: 64 additions & 0 deletions src/pkgbuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ use url::Url;

use crate::{config::Config, print_error};

use shell_words::split;
use std::env;
use std::process::Command;

#[derive(Debug, Default, Clone)]
pub enum RepoSource {
Url(Url, Option<PathBuf>),
Expand Down Expand Up @@ -409,3 +413,63 @@ pub fn read_srcinfo_from_pkgbuild(config: &Config, dir: &Path) -> Result<Srcinfo
.with_context(|| dir.display().to_string())?;
Ok(srcinfo)
}

pub fn get_editor(config: &Config) -> Result<(String, Vec<String>)> {
if let Some(editor) = &config.editor {
let editor_path =
which::which(editor).with_context(|| tr!("editor '{}' not found", editor))?;
return Ok((
editor_path.to_string_lossy().to_string(),
config.editor_flags.clone(),
));
}

if let Ok(visual) = env::var("VISUAL") {
if !visual.is_empty() {
let args: Vec<String> = split(&visual)?;
if let Some(editor) = args.first() {
if let Ok(editor_path) = which::which(editor) {
return Ok((
editor_path.to_string_lossy().to_string(),
args[1..].to_vec(),
));
}
}
}
}

if let Ok(editor) = env::var("EDITOR") {
if !editor.is_empty() {
let args: Vec<String> = split(&editor)?;
if let Some(editor) = args.first() {
if let Ok(editor_path) = which::which(editor) {
return Ok((
editor_path.to_string_lossy().to_string(),
args[1..].to_vec(),
));
}
}
}
}

bail!(tr!("no editor found, please set $EDITOR or $VISUAL"))
}

pub fn edit_pkgbuilds(config: &Config, paths: &[PathBuf]) -> Result<()> {
let (editor, mut editor_args) = get_editor(config)?;

for path in paths {
editor_args.push(path.join("PKGBUILD").to_string_lossy().to_string());
}

let status = Command::new(&editor)
.args(&editor_args)
.status()
.with_context(|| tr!("failed to run editor '{}'", editor))?;

if !status.success() {
bail!(tr!("editor did not exit successfully"));
}

Ok(())
}