From 8bc5000423aef45900b7fba112458ed586e13251 Mon Sep 17 00:00:00 2001 From: Aravind Vasudevan Date: Fri, 13 Oct 2023 19:22:47 +0000 Subject: [PATCH 1/4] Update logger.warn to logger.warning Bug: 305035810 Change-Id: Ic2b35d5c3cbe92480c24da612f29382f5d26d4aa Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/389414 Reviewed-by: Mike Frysinger Tested-by: Aravind Vasudevan Commit-Queue: Aravind Vasudevan --- main.py | 8 +++++--- project.py | 12 ++++++------ subcmds/cherry_pick.py | 2 +- subcmds/manifest.py | 6 +++--- subcmds/rebase.py | 2 +- subcmds/sync.py | 2 +- subcmds/upload.py | 6 +++--- 7 files changed, 20 insertions(+), 18 deletions(-) diff --git a/main.py b/main.py index bafa64df..9c62722f 100755 --- a/main.py +++ b/main.py @@ -566,9 +566,11 @@ repo: error: sys.exit(1) if exp > ver: - logger.warn("\n... A new version of repo (%s) is available.", exp_str) + logger.warning( + "\n... A new version of repo (%s) is available.", exp_str + ) if os.access(repo_path, os.W_OK): - logger.warn( + logger.warning( """\ ... You should upgrade soon: cp %s %s @@ -577,7 +579,7 @@ repo: error: repo_path, ) else: - logger.warn( + logger.warning( """\ ... New version is available at: %s ... The launcher is run from: %s diff --git a/project.py b/project.py index 642c123f..80c20add 100644 --- a/project.py +++ b/project.py @@ -1262,7 +1262,7 @@ class Project(object): try: platform_utils.remove(tarpath) except OSError as e: - logger.warn("warn: Cannot remove archive %s: %s", tarpath, e) + logger.warning("warn: Cannot remove archive %s: %s", tarpath, e) self._CopyAndLinkFiles() return SyncNetworkHalfResult(True) @@ -1759,7 +1759,7 @@ class Project(object): """ if self.IsDirty(): if force: - logger.warn( + logger.warning( "warning: %s: Removing dirty project: uncommitted changes " "lost.", self.RelPath(local=False), @@ -3038,7 +3038,7 @@ class Project(object): # hardlink below. if not filecmp.cmp(stock_hook, dst, shallow=False): if not quiet: - logger.warn( + logger.warning( "warn: %s: Not replacing locally modified %s hook", self.RelPath(local=False), name, @@ -4336,7 +4336,7 @@ class ManifestProject(MetaProject): self.config.SetBoolean("repo.worktree", worktree) if is_new: self.use_git_worktrees = True - logger.warn("warning: --worktree is experimental!") + logger.warning("warning: --worktree is experimental!") if archive: if is_new: @@ -4400,7 +4400,7 @@ class ManifestProject(MetaProject): self.config.SetBoolean("repo.git-lfs", git_lfs) if not is_new: - logger.warn( + logger.warning( "warning: Changing --git-lfs settings will only affect new " "project checkouts.\n" " Existing projects will require manual updates.\n" @@ -4512,7 +4512,7 @@ class ManifestProject(MetaProject): submanifest = "" if self.manifest.path_prefix: submanifest = f"for {self.manifest.path_prefix} " - logger.warn( + logger.warning( "warning: git update of superproject %s failed, " "repo sync will not use superproject to fetch source; " "while this error is not fatal, and you can continue to " diff --git a/subcmds/cherry_pick.py b/subcmds/cherry_pick.py index f9ae3e32..3d219333 100644 --- a/subcmds/cherry_pick.py +++ b/subcmds/cherry_pick.py @@ -86,7 +86,7 @@ change id will be added. p.Wait() except GitError as e: logger.error(e) - logger.warn( + logger.warning( "NOTE: When committing (please see above) and editing the " "commit message, please remove the old Change-Id-line and " "add:\n%s", diff --git a/subcmds/manifest.py b/subcmds/manifest.py index 101240d1..bb6dc930 100644 --- a/subcmds/manifest.py +++ b/subcmds/manifest.py @@ -136,7 +136,7 @@ to indicate the remote ref to push changes to via 'repo upload'. manifest.SetUseLocalManifests(not opt.ignore_local_manifests) if opt.json: - logger.warn("warning: --json is experimental!") + logger.warning("warning: --json is experimental!") doc = manifest.ToDict( peg_rev=opt.peg_rev, peg_rev_upstream=opt.peg_rev_upstream, @@ -163,13 +163,13 @@ to indicate the remote ref to push changes to via 'repo upload'. if output_file != "-": fd.close() if manifest.path_prefix: - logger.warn( + logger.warning( "Saved %s submanifest to %s", manifest.path_prefix, output_file, ) else: - logger.warn("Saved manifest to %s", output_file) + logger.warning("Saved manifest to %s", output_file) def ValidateOptions(self, opt, args): if args: diff --git a/subcmds/rebase.py b/subcmds/rebase.py index 439557c2..db1b387c 100644 --- a/subcmds/rebase.py +++ b/subcmds/rebase.py @@ -113,7 +113,7 @@ branch but need to incorporate new upstream changes "underneath" them. ) if len(args) == 1: - logger.warn( + logger.warning( "note: project %s is mapped to more than one path", args[0] ) diff --git a/subcmds/sync.py b/subcmds/sync.py index 85428b18..e1f7d019 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -1877,7 +1877,7 @@ def _PostRepoUpgrade(manifest, quiet=False): def _PostRepoFetch(rp, repo_verify=True, verbose=False): if rp.HasChanges: - logger.warn("info: A new version of repo is available") + logger.warning("info: A new version of repo is available") wrapper = Wrapper() try: rev = rp.bare_git.describe(rp.GetRevisionId()) diff --git a/subcmds/upload.py b/subcmds/upload.py index 618a10e1..4bcdfaf9 100644 --- a/subcmds/upload.py +++ b/subcmds/upload.py @@ -72,16 +72,16 @@ def _VerifyPendingCommits(branches: List[ReviewableBranch]) -> bool: # If any branch has many commits, prompt the user. if many_commits: if len(branches) > 1: - logger.warn( + logger.warning( "ATTENTION: One or more branches has an unusually high number " "of commits." ) else: - logger.warn( + logger.warning( "ATTENTION: You are uploading an unusually high number of " "commits." ) - logger.warn( + logger.warning( "YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across " "branches?)" ) From 8f4f98582ef5f99db96e383400c3acf85e0eeb52 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 14 Oct 2023 01:10:29 +0545 Subject: [PATCH 2/4] main: drop Python 2 check Python 2 can't even parse this code anymore due to syntax changes, so there's no point in checking for it explicitly. Bug: 302871152 Change-Id: I9852ace5f5079d037c60fd3ac490d77e074e6875 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/389434 Commit-Queue: Mike Frysinger Reviewed-by: Aravind Vasudevan Tested-by: Mike Frysinger --- main.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/main.py b/main.py index 9c62722f..07c360f4 100755 --- a/main.py +++ b/main.py @@ -86,27 +86,19 @@ logger = RepoLogger(__file__) MIN_PYTHON_VERSION_SOFT = (3, 6) MIN_PYTHON_VERSION_HARD = (3, 6) -if sys.version_info.major < 3: +if sys.version_info < MIN_PYTHON_VERSION_HARD: logger.error( - "repo: error: Python 2 is no longer supported; " + "repo: error: Python version is too old; " "Please upgrade to Python %d.%d+.", *MIN_PYTHON_VERSION_SOFT, ) sys.exit(1) -else: - if sys.version_info < MIN_PYTHON_VERSION_HARD: - logger.error( - "repo: error: Python 3 version is too old; " - "Please upgrade to Python %d.%d+.", - *MIN_PYTHON_VERSION_SOFT, - ) - sys.exit(1) - elif sys.version_info < MIN_PYTHON_VERSION_SOFT: - logger.error( - "repo: warning: your Python 3 version is no longer supported; " - "Please upgrade to Python %d.%d+.", - *MIN_PYTHON_VERSION_SOFT, - ) +elif sys.version_info < MIN_PYTHON_VERSION_SOFT: + logger.error( + "repo: warning: your Python version is no longer supported; " + "Please upgrade to Python %d.%d+.", + *MIN_PYTHON_VERSION_SOFT, + ) KEYBOARD_INTERRUPT_EXIT = 128 + signal.SIGINT MAX_PRINT_ERRORS = 5 From 3b8f9535c772178d8adeb1e0e4fc5916e311490a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 14 Oct 2023 01:25:50 +0545 Subject: [PATCH 3/4] hooks: drop support for Python 2 Stop running old repohooks via python2. Abort immediately with a clear error for the user. Bug: 302871152 Change-Id: I750c6cbbf3c7950e249512bb1bd023c32587eef5 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/389454 Reviewed-by: Aravind Vasudevan Tested-by: Mike Frysinger Commit-Queue: Mike Frysinger --- hooks.py | 63 +++----------------------------------------------------- 1 file changed, 3 insertions(+), 60 deletions(-) diff --git a/hooks.py b/hooks.py index decf0699..337c2627 100644 --- a/hooks.py +++ b/hooks.py @@ -12,11 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import errno -import json import os import re -import subprocess import sys import traceback import urllib.parse @@ -298,43 +295,6 @@ class RepoHook(object): return interp - def _ExecuteHookViaReexec(self, interp, context, **kwargs): - """Execute the hook script through |interp|. - - Note: Support for this feature should be dropped ~Jun 2021. - - Args: - interp: The Python program to run. - context: Basic Python context to execute the hook inside. - kwargs: Arbitrary arguments to pass to the hook script. - - Raises: - HookError: When the hooks failed for any reason. - """ - # This logic needs to be kept in sync with _ExecuteHookViaImport below. - script = """ -import json, os, sys -path = '''%(path)s''' -kwargs = json.loads('''%(kwargs)s''') -context = json.loads('''%(context)s''') -sys.path.insert(0, os.path.dirname(path)) -data = open(path).read() -exec(compile(data, path, 'exec'), context) -context['main'](**kwargs) -""" % { - "path": self._script_fullpath, - "kwargs": json.dumps(kwargs), - "context": json.dumps(context), - } - - # We pass the script via stdin to avoid OS argv limits. It also makes - # unhandled exception tracebacks less verbose/confusing for users. - cmd = [interp, "-c", "import sys; exec(sys.stdin.read())"] - proc = subprocess.Popen(cmd, stdin=subprocess.PIPE) - proc.communicate(input=script.encode("utf-8")) - if proc.returncode: - raise HookError("Failed to run %s hook." % (self._hook_type,)) - def _ExecuteHookViaImport(self, data, context, **kwargs): """Execute the hook code in |data| directly. @@ -412,30 +372,13 @@ context['main'](**kwargs) # See what version of python the hook has been written against. data = open(self._script_fullpath).read() interp = self._ExtractInterpFromShebang(data) - reexec = False if interp: prog = os.path.basename(interp) - if prog.startswith("python2") and sys.version_info.major != 2: - reexec = True - elif prog.startswith("python3") and sys.version_info.major == 2: - reexec = True - - # Attempt to execute the hooks through the requested version of - # Python. - if reexec: - try: - self._ExecuteHookViaReexec(interp, context, **kwargs) - except OSError as e: - if e.errno == errno.ENOENT: - # We couldn't find the interpreter, so fallback to - # importing. - reexec = False - else: - raise + if prog.startswith("python2"): + raise HookError("Python 2 is not supported") # Run the hook by importing directly. - if not reexec: - self._ExecuteHookViaImport(data, context, **kwargs) + self._ExecuteHookViaImport(data, context, **kwargs) finally: # Restore sys.path and CWD. sys.path = orig_syspath From 1544afe460b6d206d5494d1970db33e7f8cdfab0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 14 Oct 2023 02:10:39 +0545 Subject: [PATCH 4/4] python-support: update with current status & guidelines This doc was written back in 2019 when we were planning on the Python 3 migration. It isn't relevant anymore, and people are reading it thinking we still support Python 2. Rewrite it to match current requirements and to make it clear there is no support for older versions. Bug: 302871152 Change-Id: I2acf3aee1816a03ee0a70774db8bf4a23713a03f Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/389455 Commit-Queue: Mike Frysinger Reviewed-by: Aravind Vasudevan Tested-by: Mike Frysinger --- docs/python-support.md | 112 +++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 33 deletions(-) diff --git a/docs/python-support.md b/docs/python-support.md index 3eaaba33..e4ee96c4 100644 --- a/docs/python-support.md +++ b/docs/python-support.md @@ -1,47 +1,93 @@ # Supported Python Versions -With Python 2.7 officially going EOL on [01 Jan 2020](https://pythonclock.org/), -we need a support plan for the repo project itself. -Inevitably, there will be a long tail of users who still want to use Python 2 on -their old LTS/corp systems and have little power to change the system. +This documents the current supported Python versions, and tries to provide +guidance for when we decide to drop support for older versions. ## Summary -* Python 3.6 (released Dec 2016) is required by default starting with repo-2.x. -* Older versions of Python (e.g. v2.7) may use the legacy feature-frozen branch - based on repo-1.x. +* Python 3.6 (released Dec 2016) is required starting with repo-2.0. +* Older versions of Python (e.g. v2.7) may use old releases via the repo-1.x + branch, but no support is provided. -## Overview - -We provide a branch for Python 2 users that is feature-frozen. -Bugfixes may be added on a best-effort basis or from the community, but largely -no new features will be added, nor is support guaranteed. - -Users can select this during `repo init` time via the [repo launcher]. -Otherwise the default branches (e.g. stable & main) will be used which will -require Python 3. - -This means the [repo launcher] needs to support both Python 2 & Python 3, but -since it doesn't import any other repo code, this shouldn't be too problematic. - -The main branch will require Python 3.6 at a minimum. -If the system has an older version of Python 3, then users will have to select -the legacy Python 2 branch instead. - -### repo hooks +## repo hooks Projects that use [repo hooks] run on independent schedules. -They might migrate to Python 3 earlier or later than us. -To support them, we'll probe the shebang of the hook script and if we find an -interpreter in there that indicates a different version than repo is currently -running under, we'll attempt to reexec ourselves under that. +Since it's not possible to detect what version of Python the hooks were written +or tested against, we always import & exec them with the active Python version. -For example, a hook with a header like `#!/usr/bin/python2` will have repo -execute `/usr/bin/python2` to execute the hook code specifically if repo is -currently running Python 3. +If the user's Python is too new for the [repo hooks], then it is up to the hooks +maintainer to update. -For more details, consult the [repo hooks] documentation. +## Repo launcher + +The [repo launcher] is an independent script that can support older versions of +Python without holding back the rest of the codebase. +If it detects the current version of Python is too old, it will try to reexec +via a newer version of Python via standard `pythonX.Y` interpreter names. + +However, this is provided as a nicety when it is not onerous, and there is no +official support for older versions of Python than the rest of the codebase. + +If your default python interpreters are too old to run the launcher even though +you have newer versions installed, your choices are: + +* Modify the [repo launcher]'s shebang to suite your environment. +* Download an older version of the [repo launcher] and don't upgrade it. + Be aware that there is no guarantee old repo launchers are WILL work with + current versions of repo. Bug reports using old launchers will not be + accepted. + +## When to drop support + +So far, Python 3.6 has provided most of the interesting features that we want +(e.g. typing & f-strings), and there haven't been features in newer versions +that are critical to us. + +That said, let's assume we need functionality that only exists in Python 3.7. +How do we decide when it's acceptable to drop Python 3.6? + +1. Review the [Project References](./release-process.md#project-references) to + see what major distros are using the previous version of Python, and when + they go EOL. Generally we care about Ubuntu LTS & current/previous Debian + stable versions. + * If they're all EOL already, then go for it, drop support. + * If they aren't EOL, start a thread on [repo-discuss] to see how the user + base feels about the proposal. +1. Update the "soft" versions in the codebase. This will start warning users + that the older version is deprecated. + * Update [repo](/repo) if the launcher needs updating. + This only helps with people who download newer launchers. + * Update [main.py](/main.py) for the main codebase. + This warns for everyone regardless of [repo launcher] version. + * Update [requirements.json](/requirements.json). + This allows [repo launcher] to display warnings/errors without having + to execute the new codebase. This helps in case of syntax or module + changes where older versions won't even be able to import the new code. +1. After some grace period (ideally at least 2 quarters after the first release + with the updated soft requirements), update the "hard" versions, and then + start using the new functionality. + +## Python 2.7 & 3.0-3.5 + +> **There is no support for these versions.** +> **Do not file bugs if you are using old Python versions.** +> **Any such reports will be marked invalid and ignored.** +> **Upgrade your distro and/or runtime instead.** + +Fetch an old version of the [repo launcher]: + +```sh +$ curl https://storage.googleapis.com/git-repo-downloads/repo-2.32 > ~/.bin/repo-2.32 +$ chmod a+rx ~/.bin/repo-2.32 +``` + +Then initialize an old version of repo: + +```sh +$ repo-2.32 init --repo-rev=repo-1 ... +``` +[repo-discuss]: https://groups.google.com/forum/#!forum/repo-discuss [repo hooks]: ./repo-hooks.md [repo launcher]: ../repo