From ef649be9417b5bbd1c88f8f2a6d16575c99a0316 Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Sat, 6 Jul 2019 17:00:03 +0200 Subject: [PATCH] Add git information in sys and platform modules. --- vm/build.rs | 36 +++++++++++++++++++++++++++++++ vm/src/lib.rs | 1 + vm/src/stdlib/platform.rs | 28 ++++++++++++++++++++---- vm/src/sysmodule.rs | 15 +++++++++++-- vm/src/version.rs | 45 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 vm/build.rs create mode 100644 vm/src/version.rs diff --git a/vm/build.rs b/vm/build.rs new file mode 100644 index 0000000000..cdf4fb5508 --- /dev/null +++ b/vm/build.rs @@ -0,0 +1,36 @@ +use std::process::Command; + +fn main() { + println!("cargo:rustc-env=RUSTPYTHON_GIT_HASH={}", git_hash()); + println!( + "cargo:rustc-env=RUSTPYTHON_GIT_TIMESTAMP={}", + git_timestamp() + ); + println!("cargo:rustc-env=RUSTPYTHON_GIT_BRANCH={}", git_branch()); +} + +fn git_hash() -> String { + git(&["rev-parse", "HEAD"]) +} + +fn git_timestamp() -> String { + git(&["log", "-1", "--format=%cd"]) +} + +fn git_branch() -> String { + git(&["rev-parse", "--abbrev-ref", "HEAD"]) +} + +fn git(args: &[&str]) -> String { + command("git", args) +} + +fn command(cmd: &str, args: &[&str]) -> String { + match Command::new(cmd).args(args).output() { + Ok(output) => match String::from_utf8(output.stdout) { + Ok(s) => s, + Err(err) => format!("(output error: {})", err), + }, + Err(err) => format!("(command error: {})", err), + } +} diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 5754d98249..f520ea254d 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -60,6 +60,7 @@ pub mod stdlib; mod sysmodule; mod traceback; pub mod util; +mod version; mod vm; // pub use self::pyobject::Executor; diff --git a/vm/src/stdlib/platform.rs b/vm/src/stdlib/platform.rs index 6d4751a35f..daa70b7328 100644 --- a/vm/src/stdlib/platform.rs +++ b/vm/src/stdlib/platform.rs @@ -1,12 +1,16 @@ use crate::function::PyFuncArgs; use crate::pyobject::{PyObjectRef, PyResult}; +use crate::version; use crate::vm::VirtualMachine; pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; py_module!(vm, "platform", { + "python_branch" => ctx.new_rustfunc(platform_python_branch), + "python_build" => ctx.new_rustfunc(platform_python_build), "python_compiler" => ctx.new_rustfunc(platform_python_compiler), "python_implementation" => ctx.new_rustfunc(platform_python_implementation), + "python_revision" => ctx.new_rustfunc(platform_python_revision), "python_version" => ctx.new_rustfunc(platform_python_version), }) } @@ -18,12 +22,28 @@ fn platform_python_implementation(vm: &VirtualMachine, args: PyFuncArgs) -> PyRe fn platform_python_version(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args); - // TODO: fetch version from somewhere. - Ok(vm.new_str("4.0.0".to_string())) + Ok(vm.new_str(version::get_version_number())) } fn platform_python_compiler(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args); - let version = rustc_version_runtime::version_meta(); - Ok(vm.new_str(format!("rustc {}", version.semver))) + Ok(vm.new_str(version::get_compiler())) +} + +fn platform_python_build(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args); + let (git_hash, git_timestamp) = version::get_build_info(); + Ok(vm + .ctx + .new_tuple(vec![vm.new_str(git_hash), vm.new_str(git_timestamp)])) +} + +fn platform_python_branch(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args); + Ok(vm.new_str(version::get_git_branch())) +} + +fn platform_python_revision(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args); + Ok(vm.new_str(version::get_git_revision())) } diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index c20f7b1677..a9b1eec515 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -5,6 +5,7 @@ use crate::frame::FrameRef; use crate::function::{OptionalArg, PyFuncArgs}; use crate::obj::objstr::PyStringRef; use crate::pyobject::{IntoPyObject, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult}; +use crate::version; use crate::vm::VirtualMachine; /* @@ -160,6 +161,8 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef, builtins: PyObjectR "unknown".to_string() }; + let copyright = "Copyright (c) 2019 RustPython Team"; + let sys_doc = "This module provides access to some objects used or maintained by the interpreter and to functions that interact strongly with the interpreter. @@ -229,16 +232,23 @@ setprofile() -- set the global profiling function setrecursionlimit() -- set the max recursion depth for the interpreter settrace() -- set the global debug tracing function "; - let mut module_names: Vec<_> = vm.stdlib_inits.borrow().keys().cloned().collect(); + let mut module_names: Vec = vm.stdlib_inits.borrow().keys().cloned().collect(); module_names.push("sys".to_string()); module_names.push("builtins".to_string()); module_names.sort(); + let builtin_module_names = ctx.new_tuple( + module_names + .iter() + .map(|v| v.into_pyobject(vm).unwrap()) + .collect(), + ); let modules = ctx.new_dict(); extend_module!(vm, module, { "__name__" => ctx.new_str(String::from("sys")), "argv" => argv(ctx), - "builtin_module_names" => ctx.new_tuple(module_names.iter().map(|v| v.into_pyobject(vm).unwrap()).collect()), + "builtin_module_names" => builtin_module_names, "byteorder" => ctx.new_str(bytorder), + "copyright" => ctx.new_str(copyright.to_string()), "flags" => flags, "getrefcount" => ctx.new_rustfunc(sys_getrefcount), "getsizeof" => ctx.new_rustfunc(sys_getsizeof), @@ -260,6 +270,7 @@ settrace() -- set the global debug tracing function "path_importer_cache" => ctx.new_dict(), "pycache_prefix" => vm.get_none(), "dont_write_bytecode" => vm.new_bool(true), + "version" => vm.new_str(version::get_version()), }); modules.set_item("sys", module.clone(), vm).unwrap(); diff --git a/vm/src/version.rs b/vm/src/version.rs new file mode 100644 index 0000000000..9bb0c40083 --- /dev/null +++ b/vm/src/version.rs @@ -0,0 +1,45 @@ +/* Several function to retrieve version information. + */ + +pub fn get_version() -> String { + format!( + "{} {:?} {}", + get_version_number(), + get_build_info(), + get_compiler() + ) +} + +pub fn get_version_number() -> String { + format!( + "{}.{}.{}{}", + env!("CARGO_PKG_VERSION_MAJOR"), + env!("CARGO_PKG_VERSION_MINOR"), + env!("CARGO_PKG_VERSION_PATCH"), + option_env!("CARGO_PKG_VERSION_PRE").unwrap_or("") + ) +} + +pub fn get_compiler() -> String { + let rustc_version = rustc_version_runtime::version_meta(); + format!("rustc {}", rustc_version.semver) +} + +pub fn get_build_info() -> (String, String) { + let git_hash = get_git_revision(); + // See: https://reproducible-builds.org/docs/timestamps/ + let git_timestamp = option_env!("RUSTPYTHON_GIT_TIMESTAMP") + .unwrap_or("") + .to_string(); + (git_hash, git_timestamp) +} + +pub fn get_git_revision() -> String { + option_env!("RUSTPYTHON_GIT_HASH").unwrap_or("").to_string() +} + +pub fn get_git_branch() -> String { + option_env!("RUSTPYTHON_GIT_BRANCH") + .unwrap_or("") + .to_string() +}