From 64d98f8ee037282c35007b64c2649055c56af1db Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:03 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/ui-fulldeps/auxiliary/empty-plugin.rs | 9 +++ tests/ui-fulldeps/auxiliary/issue-13560-1.rs | 3 + tests/ui-fulldeps/auxiliary/issue-13560-2.rs | 3 + tests/ui-fulldeps/auxiliary/issue-13560-3.rs | 6 ++ tests/ui-fulldeps/auxiliary/issue-16822.rs | 20 ++++++ tests/ui-fulldeps/auxiliary/issue-18502.rs | 21 ++++++ tests/ui-fulldeps/auxiliary/issue-24106.rs | 13 ++++ tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs | 59 ++++++++++++++++ .../ui-fulldeps/auxiliary/lint-for-crate-rpass.rs | 80 ++++++++++++++++++++++ tests/ui-fulldeps/auxiliary/lint-for-crate.rs | 45 ++++++++++++ .../auxiliary/lint-group-plugin-test.rs | 44 ++++++++++++ tests/ui-fulldeps/auxiliary/lint-plugin-test.rs | 33 +++++++++ tests/ui-fulldeps/auxiliary/lint-tool-test.rs | 52 ++++++++++++++ .../auxiliary/lto-syntax-extension-lib.rs | 5 ++ .../auxiliary/lto-syntax-extension-plugin.rs | 11 +++ tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs | 10 +++ tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs | 10 +++ .../auxiliary/outlive-expansion-phase.rs | 24 +++++++ tests/ui-fulldeps/auxiliary/rlib-crate-test.rs | 12 ++++ .../auxiliary/syntax-extension-with-dll-deps-1.rs | 7 ++ 20 files changed, 467 insertions(+) create mode 100644 tests/ui-fulldeps/auxiliary/empty-plugin.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-13560-1.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-13560-2.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-13560-3.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-16822.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-18502.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-24106.rs create mode 100644 tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs create mode 100644 tests/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs create mode 100644 tests/ui-fulldeps/auxiliary/lint-for-crate.rs create mode 100644 tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs create mode 100644 tests/ui-fulldeps/auxiliary/lint-plugin-test.rs create mode 100644 tests/ui-fulldeps/auxiliary/lint-tool-test.rs create mode 100644 tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs create mode 100644 tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs create mode 100644 tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs create mode 100644 tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs create mode 100644 tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs create mode 100644 tests/ui-fulldeps/auxiliary/rlib-crate-test.rs create mode 100644 tests/ui-fulldeps/auxiliary/syntax-extension-with-dll-deps-1.rs (limited to 'tests/ui-fulldeps/auxiliary') diff --git a/tests/ui-fulldeps/auxiliary/empty-plugin.rs b/tests/ui-fulldeps/auxiliary/empty-plugin.rs new file mode 100644 index 000000000..c24cdc97a --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/empty-plugin.rs @@ -0,0 +1,9 @@ +// force-host + +#![feature(rustc_private)] + +extern crate rustc_driver; +use rustc_driver::plugin::Registry; + +#[no_mangle] +fn __rustc_plugin_registrar(_: &mut Registry) {} diff --git a/tests/ui-fulldeps/auxiliary/issue-13560-1.rs b/tests/ui-fulldeps/auxiliary/issue-13560-1.rs new file mode 100644 index 000000000..c3a2ae679 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-13560-1.rs @@ -0,0 +1,3 @@ +// no-prefer-dynamic + +#![crate_type = "dylib"] diff --git a/tests/ui-fulldeps/auxiliary/issue-13560-2.rs b/tests/ui-fulldeps/auxiliary/issue-13560-2.rs new file mode 100644 index 000000000..39c261e11 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-13560-2.rs @@ -0,0 +1,3 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] diff --git a/tests/ui-fulldeps/auxiliary/issue-13560-3.rs b/tests/ui-fulldeps/auxiliary/issue-13560-3.rs new file mode 100644 index 000000000..e991bcc1a --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-13560-3.rs @@ -0,0 +1,6 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +#[macro_use] #[no_link] extern crate issue_13560_1 as t1; +#[macro_use] extern crate issue_13560_2 as t2; diff --git a/tests/ui-fulldeps/auxiliary/issue-16822.rs b/tests/ui-fulldeps/auxiliary/issue-16822.rs new file mode 100644 index 000000000..9042dd391 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-16822.rs @@ -0,0 +1,20 @@ +#![crate_type="lib"] + +use std::cell::RefCell; + +pub struct Window{ + pub data: RefCell +} + +impl Window { + pub fn update(&self, e: i32) { + match e { + 1 => self.data.borrow_mut().update(), + _ => {} + } + } +} + +pub trait Update { + fn update(&mut self); +} diff --git a/tests/ui-fulldeps/auxiliary/issue-18502.rs b/tests/ui-fulldeps/auxiliary/issue-18502.rs new file mode 100644 index 000000000..4d4230607 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-18502.rs @@ -0,0 +1,21 @@ +#![crate_type="lib"] + +struct Foo; +// This is the ICE trigger +struct Formatter; + +trait Show { + fn fmt(&self); +} + +impl Show for Foo { + fn fmt(&self) {} +} + +fn bar(f: extern "Rust" fn(&T), t: &T) { } + +// ICE requirement: this has to be marked as inline +#[inline] +pub fn baz() { + bar(Show::fmt, &Foo); +} diff --git a/tests/ui-fulldeps/auxiliary/issue-24106.rs b/tests/ui-fulldeps/auxiliary/issue-24106.rs new file mode 100644 index 000000000..2c6a60348 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-24106.rs @@ -0,0 +1,13 @@ +#![crate_type="lib"] + +enum E { E0 = 0, E1 = 1 } +const E0_U8: u8 = E::E0 as u8; +const E1_U8: u8 = E::E1 as u8; + +pub fn go() { + match 0 { + E0_U8 => (), + E1_U8 => (), + _ => (), + } +} diff --git a/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs new file mode 100644 index 000000000..c05443488 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -0,0 +1,59 @@ +#![feature(plugin, rustc_private)] +#![crate_type = "dylib"] + +extern crate rustc_ast_pretty; +extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; +extern crate rustc_ast; +extern crate rustc_span; + +use rustc_ast_pretty::pprust; +use rustc_driver::plugin::Registry; +use rustc_hir as hir; +use rustc_hir::intravisit; +use rustc_hir::Node; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_span::source_map; + +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]); + reg.lint_store.register_late_pass(|_| Box::new(MissingAllowedAttrPass)); +} + +declare_lint! { + MISSING_ALLOWED_ATTR, + Deny, + "Checks for missing `allowed_attr` attribute" +} + +declare_lint_pass!(MissingAllowedAttrPass => [MISSING_ALLOWED_ATTR]); + +impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + _: intravisit::FnKind<'tcx>, + _: &'tcx hir::FnDecl, + _: &'tcx hir::Body, + span: source_map::Span, + id: hir::HirId, + ) { + let item = match cx.tcx.hir().get(id) { + Node::Item(item) => item, + _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id), + }; + + let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr"); + if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) { + cx.lint( + MISSING_ALLOWED_ATTR, + "Missing 'allowed_attr' attribute", + |lint| lint.set_span(span) + ); + } + } +} diff --git a/tests/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/tests/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs new file mode 100644 index 000000000..a3b570ad8 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -0,0 +1,80 @@ +// force-host + +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_lint; +extern crate rustc_span; +#[macro_use] +extern crate rustc_session; +extern crate rustc_ast; + +use rustc_ast::attr; +use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass}; +use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::symbol::Symbol; + +macro_rules! fake_lint_pass { + ($struct:ident, $($attr:expr),*) => { + struct $struct; + + impl LintPass for $struct { + fn name(&self) -> &'static str { + stringify!($struct) + } + } + + impl LateLintPass<'_> for $struct { + fn check_crate(&mut self, cx: &LateContext) { + let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let span = cx.tcx.def_span(CRATE_DEF_ID); + $( + if !cx.sess().contains_name(attrs, $attr) { + cx.lint(CRATE_NOT_OKAY, |lint| { + let msg = format!("crate is not marked with #![{}]", $attr); + lint.build(&msg).set_span(span).emit(); + }); + } + )* + } + } + + } +} + +declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]"); +declare_lint!(CRATE_NOT_RED, Warn, "crate not marked with #![crate_red]"); +declare_lint!(CRATE_NOT_BLUE, Warn, "crate not marked with #![crate_blue]"); +declare_lint!(CRATE_NOT_GREY, Warn, "crate not marked with #![crate_grey]"); +declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]"); + +fake_lint_pass! { + PassOkay, + Symbol::intern("crate_okay") +} + +fake_lint_pass! { + PassRedBlue, + Symbol::intern("crate_red"), Symbol::intern("crate_blue") +} + +fake_lint_pass! { + PassGreyGreen, + Symbol::intern("crate_grey"), Symbol::intern("crate_green") +} + +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[ + &CRATE_NOT_OKAY, + &CRATE_NOT_RED, + &CRATE_NOT_BLUE, + &CRATE_NOT_GREY, + &CRATE_NOT_GREEN, + ]); + reg.lint_store.register_late_pass(|_| Box::new(PassOkay)); + reg.lint_store.register_late_pass(|_| Box::new(PassRedBlue)); + reg.lint_store.register_late_pass(|_| Box::new(PassGreyGreen)); +} diff --git a/tests/ui-fulldeps/auxiliary/lint-for-crate.rs b/tests/ui-fulldeps/auxiliary/lint-for-crate.rs new file mode 100644 index 000000000..073da688c --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -0,0 +1,45 @@ +// force-host + +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_hir; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; +extern crate rustc_ast; +extern crate rustc_span; + +use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_span::def_id::CRATE_DEF_ID; +use rustc_span::symbol::Symbol; + +declare_lint! { + CRATE_NOT_OKAY, + Warn, + "crate not marked with #![crate_okay]" +} + +declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); + +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_crate(&mut self, cx: &LateContext) { + let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); + let span = cx.tcx.def_span(CRATE_DEF_ID); + if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) { + cx.lint( + CRATE_NOT_OKAY, + "crate is not marked with #![crate_okay]", + |lint| lint.set_span(span) + ); + } + } +} + +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]); + reg.lint_store.register_late_pass(|_| Box::new(Pass)); +} diff --git a/tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs new file mode 100644 index 000000000..4a41e7fbb --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -0,0 +1,44 @@ +// force-host + +#![feature(rustc_private)] + +// Load rustc as a plugin to get macros. +extern crate rustc_driver; +extern crate rustc_hir; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; + +use rustc_driver::plugin::Registry; +use rustc_lint::{LateContext, LateLintPass, LintArray, LintContext, LintId, LintPass}; + +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); + +declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'"); + +declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]); + +impl<'tcx> LateLintPass<'tcx> for Pass { + fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) { + match it.ident.as_str() { + "lintme" => cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)), + "pleaselintme" => { + cx.lint(PLEASE_LINT, "item is named 'pleaselintme'", |lint| lint.set_span(it.span)) + } + _ => {} + } + } +} + +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]); + reg.lint_store.register_late_pass(|_| Box::new(Pass)); + reg.lint_store.register_group( + true, + "lint_me", + None, + vec![LintId::of(&TEST_LINT), LintId::of(&PLEASE_LINT)], + ); +} diff --git a/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs b/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs new file mode 100644 index 000000000..30956deb7 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -0,0 +1,33 @@ +// force-host + +#![feature(rustc_private)] + +extern crate rustc_ast; + +// Load rustc as a plugin to get macros +extern crate rustc_driver; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; + +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc_ast as ast; +declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); + +declare_lint_pass!(Pass => [TEST_LINT]); + +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { + if it.ident.name.as_str() == "lintme" { + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); + } + } +} + +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[&TEST_LINT]); + reg.lint_store.register_early_pass(|| Box::new(Pass)); +} diff --git a/tests/ui-fulldeps/auxiliary/lint-tool-test.rs b/tests/ui-fulldeps/auxiliary/lint-tool-test.rs new file mode 100644 index 000000000..c2c024865 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -0,0 +1,52 @@ +#![feature(rustc_private)] + +extern crate rustc_ast; + +// Load rustc as a plugin to get macros +extern crate rustc_driver; +#[macro_use] +extern crate rustc_lint; +#[macro_use] +extern crate rustc_session; + +use rustc_driver::plugin::Registry; +use rustc_lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintId, LintPass}; +use rustc_ast as ast; +declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); +declare_tool_lint!( + /// Some docs + pub clippy::TEST_GROUP, + Warn, "Warn about other stuff" +); + +declare_tool_lint!( + /// Some docs + pub rustc::TEST_RUSTC_TOOL_LINT, + Deny, + "Deny internal stuff" +); + +declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP, TEST_RUSTC_TOOL_LINT]); + +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { + if it.ident.name.as_str() == "lintme" { + cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)); + } + if it.ident.name.as_str() == "lintmetoo" { + cx.lint(TEST_GROUP, "item is named 'lintmetoo'", |lint| lint.set_span(it.span)); + } + } +} + +#[no_mangle] +fn __rustc_plugin_registrar(reg: &mut Registry) { + reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]); + reg.lint_store.register_early_pass(|| Box::new(Pass)); + reg.lint_store.register_group( + true, + "clippy::group", + Some("clippy_group"), + vec![LintId::of(&TEST_LINT), LintId::of(&TEST_GROUP)], + ); +} diff --git a/tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs b/tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs new file mode 100644 index 000000000..954a1e554 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lto-syntax-extension-lib.rs @@ -0,0 +1,5 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +pub fn foo() {} diff --git a/tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs b/tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs new file mode 100644 index 000000000..9b075c1a5 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs @@ -0,0 +1,11 @@ +// force-host + +#![feature(rustc_private)] + +extern crate rustc_middle; +extern crate rustc_driver; + +use rustc_driver::plugin::Registry; + +#[no_mangle] +fn __rustc_plugin_registrar(_reg: &mut Registry) {} diff --git a/tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs b/tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs new file mode 100644 index 000000000..fd6e9e20f --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/multiple-plugins-1.rs @@ -0,0 +1,10 @@ +#![crate_type = "dylib"] +#![feature(rustc_private)] + +extern crate rustc_middle; +extern crate rustc_driver; + +use rustc_driver::plugin::Registry; + +#[no_mangle] +fn __rustc_plugin_registrar(_: &mut Registry) {} diff --git a/tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs b/tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs new file mode 100644 index 000000000..fd6e9e20f --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/multiple-plugins-2.rs @@ -0,0 +1,10 @@ +#![crate_type = "dylib"] +#![feature(rustc_private)] + +extern crate rustc_middle; +extern crate rustc_driver; + +use rustc_driver::plugin::Registry; + +#[no_mangle] +fn __rustc_plugin_registrar(_: &mut Registry) {} diff --git a/tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs b/tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs new file mode 100644 index 000000000..e83dfe804 --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/outlive-expansion-phase.rs @@ -0,0 +1,24 @@ +// force-host + +#![feature(rustc_private)] + +extern crate rustc_middle; +extern crate rustc_driver; + +use std::any::Any; +use std::cell::RefCell; +use rustc_driver::plugin::Registry; + +struct Foo { + foo: isize +} + +impl Drop for Foo { + fn drop(&mut self) {} +} + +#[no_mangle] +fn __rustc_plugin_registrar(_: &mut Registry) { + thread_local!(static FOO: RefCell>> = RefCell::new(None)); + FOO.with(|s| *s.borrow_mut() = Some(Box::new(Foo { foo: 10 }) as Box)); +} diff --git a/tests/ui-fulldeps/auxiliary/rlib-crate-test.rs b/tests/ui-fulldeps/auxiliary/rlib-crate-test.rs new file mode 100644 index 000000000..3ba73538e --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/rlib-crate-test.rs @@ -0,0 +1,12 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![feature(rustc_private)] + +extern crate rustc_middle; +extern crate rustc_driver; + +use rustc_driver::plugin::Registry; + +#[no_mangle] +fn __rustc_plugin_registrar(_: &mut Registry) {} diff --git a/tests/ui-fulldeps/auxiliary/syntax-extension-with-dll-deps-1.rs b/tests/ui-fulldeps/auxiliary/syntax-extension-with-dll-deps-1.rs new file mode 100644 index 000000000..8b00fb81c --- /dev/null +++ b/tests/ui-fulldeps/auxiliary/syntax-extension-with-dll-deps-1.rs @@ -0,0 +1,7 @@ +// force-host + +#![crate_type = "dylib"] + +pub fn the_answer() -> isize { + 2 +} -- cgit v1.2.3