Skip to content

Commit a458ade

Browse files
authored
v.utils: update githash to be able to get the githash of every passed project (#21178)
1 parent bb42e1c commit a458ade

File tree

4 files changed

+70
-48
lines changed

4 files changed

+70
-48
lines changed

cmd/tools/vup.v

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ fn main() {
3535
os.chdir(app.vroot)!
3636
println('Updating V...')
3737
app.update_from_master()
38-
v_hash := version.githash(false)
39-
current_hash := version.githash(true)
38+
v_hash := @VCURRENTHASH
39+
current_hash := version.githash(vroot) or { v_hash }
4040
// println(v_hash)
4141
// println(current_hash)
4242
if v_hash == current_hash && !app.skip_current {

vlib/v/checker/checker.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ pub fn new_checker(table &ast.Table, pref_ &pref.Preferences) &Checker {
149149
pref: pref_
150150
timers: util.new_timers(should_print: timers_should_print, label: 'checker')
151151
match_exhaustive_cutoff_limit: pref_.checker_match_exhaustive_cutoff_limit
152-
v_current_commit_hash: version.githash(pref_.building_v)
152+
v_current_commit_hash: if pref_.building_v { version.githash(pref_.vroot) or {
153+
@VCURRENTHASH} } else { @VCURRENTHASH }
153154
}
154155
checker.comptime = &comptime.ComptimeInfo{
155156
resolver: checker

vlib/v/util/version/version.c.v

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub fn vhash() string {
1717

1818
pub fn full_hash() string {
1919
build_hash := vhash()
20-
current_hash := githash(false)
20+
current_hash := @VCURRENTHASH
2121
if build_hash == current_hash {
2222
return build_hash
2323
}
@@ -29,52 +29,35 @@ pub fn full_v_version(is_verbose bool) string {
2929
if is_verbose {
3030
return 'V ${version.v_version} ${full_hash()}'
3131
}
32-
hash := githash(false)
33-
return 'V ${version.v_version} ${hash}'
32+
return 'V ${version.v_version} ${@VCURRENTHASH}'
3433
}
3534

36-
// githash(x) returns the current git commit hash.
37-
// When x is false, it is very fast - it just returns a predefined C constant.
38-
// When x is true, it tries to get the current commit hash, by parsing the
39-
// relevant files in the .git/ folder, or if that is not possible
40-
// for example when using a V from a V binary release, that does not have .git/
41-
// defaults to getting the predefined C constant again.
42-
// Note: githash(true) must be called only when v detects that it builds itself.
43-
// For all other programs, githash(false) should be used.
44-
pub fn githash(should_get_from_filesystem bool) string {
45-
for {
46-
// The `for` construct here is used as a goto substitute.
47-
// The code in this function will break out of the `for`
48-
// if it detects an error and can not continue.
49-
if should_get_from_filesystem {
50-
vexe := os.getenv('VEXE')
51-
vroot := os.dir(vexe)
52-
// .git/HEAD
53-
git_head_file := os.join_path(vroot, '.git', 'HEAD')
54-
if !os.exists(git_head_file) {
55-
break
56-
}
57-
// 'ref: refs/heads/master' ... the current branch name
58-
head_content := os.read_file(git_head_file) or { break }
59-
mut current_branch_hash := head_content
60-
if head_content.starts_with('ref: ') {
61-
gcbranch_rel_path := head_content.replace('ref: ', '').trim_space()
62-
gcbranch_file := os.join_path(vroot, '.git', gcbranch_rel_path)
63-
// .git/refs/heads/master
64-
if !os.exists(gcbranch_file) {
65-
break
66-
}
67-
// get the full commit hash contained in the ref heads file
68-
branch_hash := os.read_file(gcbranch_file) or { break }
69-
current_branch_hash = branch_hash
70-
}
71-
desired_hash_length := 7
72-
if current_branch_hash.len > desired_hash_length {
73-
return current_branch_hash[0..desired_hash_length]
74-
}
35+
// githash tries to find the current git commit hash for the specified
36+
// project path by parsing the relevant files in its `.git/` folder.
37+
pub fn githash(path string) !string {
38+
// .git/HEAD
39+
git_head_file := os.join_path(path, '.git', 'HEAD')
40+
if !os.exists(git_head_file) {
41+
return error('failed to find `${git_head_file}`')
42+
}
43+
// 'ref: refs/heads/master' ... the current branch name
44+
head_content := os.read_file(git_head_file) or {
45+
return error('failed to read `${git_head_file}`')
46+
}
47+
current_branch_hash := if head_content.starts_with('ref: ') {
48+
rev_rel_path := head_content.replace('ref: ', '').trim_space()
49+
rev_file := os.join_path(path, '.git', rev_rel_path)
50+
// .git/refs/heads/master
51+
if !os.exists(rev_file) {
52+
return error('failed to find revision file `${rev_file}`')
7553
}
76-
break
54+
// get the full commit hash contained in the ref heads file
55+
os.read_file(rev_file) or { return error('failed to read revision file `${rev_file}`') }
56+
} else {
57+
head_content
58+
}
59+
desired_hash_length := 7
60+
return current_branch_hash[0..desired_hash_length] or {
61+
error('failed to limit hash `${current_branch_hash}` to ${desired_hash_length} characters')
7762
}
78-
79-
return @VCURRENTHASH
8063
}

vlib/v/util/version/version_test.v

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import v.util.version
2+
import os
3+
4+
fn test_githash() {
5+
if !os.exists(os.join_path(@VMODROOT, '.git')) {
6+
eprintln('> skipping test due to missing V .git directory')
7+
return
8+
}
9+
sha := version.githash(@VMODROOT)!
10+
assert sha == @VCURRENTHASH
11+
12+
git_proj_path := os.join_path(os.vtmp_dir(), 'test_githash')
13+
defer {
14+
os.rmdir_all(git_proj_path) or {}
15+
}
16+
os.execute_opt('git init ${git_proj_path}')!
17+
os.chdir(git_proj_path)!
18+
if sha_ := version.githash(git_proj_path) {
19+
assert false, 'Should not have found an unknown revision'
20+
} else {
21+
assert err.msg().contains('failed to find revision file'), err.msg()
22+
}
23+
os.execute_opt('git config user.name') or {
24+
os.execute_opt('git config user.email "ci@vlang.io"')!
25+
os.execute_opt('git config user.name "V CI"')!
26+
}
27+
os.write_file('v.mod', '')!
28+
os.execute_opt('git add .')!
29+
os.execute_opt('git commit -m "test1"')!
30+
test_rev := os.execute_opt('git rev-parse --short HEAD')!.output.trim_space()
31+
assert test_rev == version.githash(git_proj_path)!
32+
os.write_file('README.md', '')!
33+
os.execute_opt('git add .')!
34+
os.execute_opt('git commit -m "test2"')!
35+
test_rev2 := os.execute_opt('git rev-parse --short HEAD')!.output.trim_space()
36+
assert test_rev2 != test_rev
37+
assert test_rev2 == version.githash(git_proj_path)!
38+
}

0 commit comments

Comments
 (0)