mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Provide better output when downloading versions fails
- include stdout/stderr when utf8_output() fails - don't swallow the error returned by handle_Version_install_or_update - skip codesigning when NODMG set Closes #4224
This commit is contained in:
parent
aee71afebe
commit
00bc0354c9
3 changed files with 69 additions and 32 deletions
|
@ -38,19 +38,19 @@ cp ../pyproject.toml "$APP_LAUNCHER/Contents/Resources/"
|
||||||
cp ../../../.python-version "$APP_LAUNCHER/Contents/Resources/"
|
cp ../../../.python-version "$APP_LAUNCHER/Contents/Resources/"
|
||||||
cp ../versions.py "$APP_LAUNCHER/Contents/Resources/"
|
cp ../versions.py "$APP_LAUNCHER/Contents/Resources/"
|
||||||
|
|
||||||
# Codesign
|
# Codesign/bundle
|
||||||
for i in "$APP_LAUNCHER/Contents/MacOS/uv" "$APP_LAUNCHER/Contents/MacOS/launcher" "$APP_LAUNCHER"; do
|
if [ -z "$NODMG" ]; then
|
||||||
|
for i in "$APP_LAUNCHER/Contents/MacOS/uv" "$APP_LAUNCHER/Contents/MacOS/launcher" "$APP_LAUNCHER"; do
|
||||||
codesign --force -vvvv -o runtime -s "Developer ID Application:" \
|
codesign --force -vvvv -o runtime -s "Developer ID Application:" \
|
||||||
--entitlements entitlements.python.xml \
|
--entitlements entitlements.python.xml \
|
||||||
"$i"
|
"$i"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Check
|
# Check
|
||||||
codesign -vvv "$APP_LAUNCHER"
|
codesign -vvv "$APP_LAUNCHER"
|
||||||
spctl -a "$APP_LAUNCHER"
|
spctl -a "$APP_LAUNCHER"
|
||||||
|
|
||||||
# Notarize and bundle (skip if NODMG is set)
|
# Notarize and build dmg
|
||||||
if [ -z "$NODMG" ]; then
|
|
||||||
./notarize.sh "$OUTPUT_DIR"
|
./notarize.sh "$OUTPUT_DIR"
|
||||||
./dmg/build.sh "$OUTPUT_DIR"
|
./dmg/build.sh "$OUTPUT_DIR"
|
||||||
fi
|
fi
|
|
@ -378,9 +378,7 @@ fn main_menu_loop(state: &State) -> Result<()> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
choice @ (MainMenuChoice::Latest | MainMenuChoice::Version(_)) => {
|
choice @ (MainMenuChoice::Latest | MainMenuChoice::Version(_)) => {
|
||||||
if handle_version_install_or_update(state, choice.clone()).is_err() {
|
handle_version_install_or_update(state, choice.clone())?;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -650,7 +648,13 @@ fn fetch_versions(state: &State) -> Result<Vec<String>> {
|
||||||
.args(["run", "--no-project"])
|
.args(["run", "--no-project"])
|
||||||
.arg(&versions_script);
|
.arg(&versions_script);
|
||||||
|
|
||||||
let output = cmd.utf8_output()?;
|
let output = match cmd.utf8_output() {
|
||||||
|
Ok(output) => output,
|
||||||
|
Err(e) => {
|
||||||
|
print!("Unable to check for Anki versions. Please check your internet connection.\n\n");
|
||||||
|
return Err(e.into());
|
||||||
|
}
|
||||||
|
};
|
||||||
let versions = serde_json::from_str(&output.stdout).context("Failed to parse versions JSON")?;
|
let versions = serde_json::from_str(&output.stdout).context("Failed to parse versions JSON")?;
|
||||||
Ok(versions)
|
Ok(versions)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,24 @@ use snafu::ensure;
|
||||||
use snafu::ResultExt;
|
use snafu::ResultExt;
|
||||||
use snafu::Snafu;
|
use snafu::Snafu;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CodeDisplay(Option<i32>);
|
||||||
|
|
||||||
|
impl std::fmt::Display for CodeDisplay {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.0 {
|
||||||
|
Some(code) => write!(f, "{code}"),
|
||||||
|
None => write!(f, "?"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<i32>> for CodeDisplay {
|
||||||
|
fn from(code: Option<i32>) -> Self {
|
||||||
|
CodeDisplay(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[snafu(display("Failed to execute: {cmdline}"))]
|
#[snafu(display("Failed to execute: {cmdline}"))]
|
||||||
|
@ -18,8 +36,15 @@ pub enum Error {
|
||||||
cmdline: String,
|
cmdline: String,
|
||||||
source: std::io::Error,
|
source: std::io::Error,
|
||||||
},
|
},
|
||||||
#[snafu(display("Failed with code {code:?}: {cmdline}"))]
|
#[snafu(display("Failed to run ({code}): {cmdline}"))]
|
||||||
ReturnedError { cmdline: String, code: Option<i32> },
|
ReturnedError { cmdline: String, code: CodeDisplay },
|
||||||
|
#[snafu(display("Failed to run ({code}): {cmdline}: {stdout}{stderr}"))]
|
||||||
|
ReturnedWithOutputError {
|
||||||
|
cmdline: String,
|
||||||
|
code: CodeDisplay,
|
||||||
|
stdout: String,
|
||||||
|
stderr: String,
|
||||||
|
},
|
||||||
#[snafu(display("Couldn't decode stdout/stderr as utf8"))]
|
#[snafu(display("Couldn't decode stdout/stderr as utf8"))]
|
||||||
InvalidUtf8 {
|
InvalidUtf8 {
|
||||||
cmdline: String,
|
cmdline: String,
|
||||||
|
@ -71,31 +96,36 @@ impl CommandExt for Command {
|
||||||
status.success(),
|
status.success(),
|
||||||
ReturnedSnafu {
|
ReturnedSnafu {
|
||||||
cmdline: get_cmdline(self),
|
cmdline: get_cmdline(self),
|
||||||
code: status.code(),
|
code: CodeDisplay::from(status.code()),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn utf8_output(&mut self) -> Result<Utf8Output> {
|
fn utf8_output(&mut self) -> Result<Utf8Output> {
|
||||||
|
let cmdline = get_cmdline(self);
|
||||||
let output = self.output().with_context(|_| DidNotExecuteSnafu {
|
let output = self.output().with_context(|_| DidNotExecuteSnafu {
|
||||||
cmdline: get_cmdline(self),
|
cmdline: cmdline.clone(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
let stdout = String::from_utf8(output.stdout).with_context(|_| InvalidUtf8Snafu {
|
||||||
|
cmdline: cmdline.clone(),
|
||||||
|
})?;
|
||||||
|
let stderr = String::from_utf8(output.stderr).with_context(|_| InvalidUtf8Snafu {
|
||||||
|
cmdline: cmdline.clone(),
|
||||||
|
})?;
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
output.status.success(),
|
output.status.success(),
|
||||||
ReturnedSnafu {
|
ReturnedWithOutputSnafu {
|
||||||
cmdline: get_cmdline(self),
|
cmdline,
|
||||||
code: output.status.code(),
|
code: CodeDisplay::from(output.status.code()),
|
||||||
|
stdout: stdout.clone(),
|
||||||
|
stderr: stderr.clone(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Ok(Utf8Output {
|
|
||||||
stdout: String::from_utf8(output.stdout).with_context(|_| InvalidUtf8Snafu {
|
Ok(Utf8Output { stdout, stderr })
|
||||||
cmdline: get_cmdline(self),
|
|
||||||
})?,
|
|
||||||
stderr: String::from_utf8(output.stderr).with_context(|_| InvalidUtf8Snafu {
|
|
||||||
cmdline: get_cmdline(self),
|
|
||||||
})?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_spawn(&mut self) -> Result<std::process::Child> {
|
fn ensure_spawn(&mut self) -> Result<std::process::Child> {
|
||||||
|
@ -135,7 +165,10 @@ mod test {
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
Command::new("false").ensure_success(),
|
Command::new("false").ensure_success(),
|
||||||
Err(Error::ReturnedError { code: Some(1), .. })
|
Err(Error::ReturnedError {
|
||||||
|
code: CodeDisplay(_),
|
||||||
|
..
|
||||||
|
})
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue