diff --git a/BUILD.gn b/BUILD.gn index 1bf864be99..4175f04800 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -104,14 +104,26 @@ branding = read_file("shell/app/BRANDING.json", "json") electron_project_name = branding.project_name electron_product_name = branding.product_name electron_mac_bundle_id = branding.mac_bundle_id -electron_version = exec_script("script/print-version.py", - [], - "trim string", - [ - ".git/packed-refs", - ".git/HEAD", - "script/lib/get-version.js", - ]) + +if (override_electron_version != "") { + electron_version = override_electron_version +} else { + # When building from source code tarball there is no git tag available and + # builders must explicitly pass override_electron_version in gn args. + # This read_file call will assert if there is no git information, without it + # gn will generate a malformed build configuration and ninja will get into + # infinite loop. + read_file(".git/packed-refs", "string") + + # Set electron version from git tag. + electron_version = exec_script("script/get-git-version.py", + [], + "trim string", + [ + ".git/packed-refs", + ".git/HEAD", + ]) +} if (is_mas_build) { assert(is_mac, diff --git a/buildflags/buildflags.gni b/buildflags/buildflags.gni index d7270e21bf..9abe9852d2 100644 --- a/buildflags/buildflags.gni +++ b/buildflags/buildflags.gni @@ -18,4 +18,9 @@ declare_args() { # Enable Spellchecker support enable_builtin_spellchecker = true + + # The version of Electron. + # Packagers and vendor builders should set this in gn args to avoid running + # the script that reads git tag. + override_electron_version = "" } diff --git a/script/get-git-version.py b/script/get-git-version.py new file mode 100755 index 0000000000..ca3bc07ba7 --- /dev/null +++ b/script/get-git-version.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import subprocess +import os + +# Find the nearest tag to the current HEAD. +# This is equivalent to our old logic of "use a value in package.json" for the +# following reasons: +# +# 1. Whenever we updated the package.json we ALSO pushed a tag with the same +# version. +# 2. Whenever we _reverted_ a bump all we actually did was push a commit that +# deleted the tag and changed the version number back. +# +# The only difference in the "git describe" technique is that technically a +# commit can "change" its version number if a tag is created / removed +# retroactively. i.e. the first time a commit is pushed it will be 1.2.3 +# and after the tag is made rebuilding the same commit will result in it being +# 1.2.4. + +try: + output = subprocess.check_output( + ['git', 'describe', '--tags', '--abbrev=0'], + cwd=os.path.abspath(os.path.join(os.path.dirname(__file__), '..')), + stderr=subprocess.PIPE, + universal_newlines=True) + version = output.strip().replace('v', '') + print(version) +except Exception: + # When there is error we print a null version string instead of throwing an + # exception, this is because for linux/bsd packages and some vendor builds + # electron is built from a source code tarball and there is no git information + # there. + print('0.0.0-no-git-tag-found') diff --git a/script/lib/get-version.js b/script/lib/get-version.js index 3e1cc62acc..19da50a85b 100644 --- a/script/lib/get-version.js +++ b/script/lib/get-version.js @@ -1,22 +1,30 @@ const { spawnSync } = require('node:child_process'); +const fs = require('node:fs'); const path = require('node:path'); +const { ELECTRON_DIR, getOutDir } = require('./utils'); + +// Print the value of electron_version set in gn config. module.exports.getElectronVersion = () => { - // Find the nearest tag to the current HEAD - // This is equivilant to our old logic of "use a value in package.json" for the following reasons - // - // 1. Whenever we updated the package.json we ALSO pushed a tag with the same version - // 2. Whenever we _reverted_ a bump all we actually did was push a commit that deleted the tag and changed the version number back - // - // The only difference in the "git describe" technique is that technically a commit can "change" it's version - // number if a tag is created / removed retroactively. i.e. the first time a commit is pushed it will be 1.2.3 - // and after the tag is made rebuilding the same commit will result in it being 1.2.4 - const output = spawnSync('git', ['describe', '--tags', '--abbrev=0'], { - cwd: path.resolve(__dirname, '..', '..') - }); - if (output.status !== 0) { - console.error(output.stderr); - throw new Error('Failed to get current electron version'); + // Read the override_electron_version from args.gn file. + try { + const outDir = path.resolve(ELECTRON_DIR, '..', 'out', getOutDir()); + const content = fs.readFileSync(path.join(outDir, 'args.gn')); + const regex = /override_electron_version\s*=\s*["']([^"']+)["']/; + const match = content.toString().match(regex); + if (match) { + return match[1]; + } + } catch (error) { + // Error may happen when trying to get version before running gn, which is a + // valid case and error will be ignored. } - return output.stdout.toString().trim().replace(/^v/g, ''); + // Most win32 machines have python.exe but no python3.exe. + const python = process.platform === 'win32' ? 'python.exe' : 'python3'; + // Get the version from git tag if it is not defined in gn args. + const output = spawnSync(python, [path.join(ELECTRON_DIR, 'script', 'get-git-version.py')]); + if (output.status !== 0) { + throw new Error(`Failed to get git tag, script quit with ${output.status}: ${output.stdout}`); + } + return output.stdout.toString().trim(); }; diff --git a/script/print-version.py b/script/print-version.py deleted file mode 100644 index 20ec2231a2..0000000000 --- a/script/print-version.py +++ /dev/null @@ -1,3 +0,0 @@ -from lib.util import get_electron_version - -print(get_electron_version())