>From 7a106efa3268cad77c6b21b798296284923b4a2f Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 5 Aug 2022 19:24:14 +0200 Subject: [PATCH 05/12] gnulib-tool.py: Fix link_if_changed function. * pygnulib/constants.py (joinpath): Fix comment. (as_link_value_at_dest): New function, extracted from link_relative. (link_relative): Use it. (link_if_changed): Really don't replace the symbolic link if it does not need to change. --- ChangeLog | 7 +++++++ pygnulib/constants.py | 42 +++++++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index e838c4610c..c48eabe254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2022-08-05 Bruno Haible + gnulib-tool.py: Fix link_if_changed function. + * pygnulib/constants.py (joinpath): Fix comment. + (as_link_value_at_dest): New function, extracted from link_relative. + (link_relative): Use it. + (link_if_changed): Really don't replace the symbolic link if it does not + need to change. + gnulib-tool.py: Fix 'Unused import' warnings. * gnulib-tool.py: Remove unused imports. * pygnulib/*.py: Likewise. diff --git a/pygnulib/constants.py b/pygnulib/constants.py index 313aac94a1..46c0cbc152 100644 --- a/pygnulib/constants.py +++ b/pygnulib/constants.py @@ -244,10 +244,10 @@ def cleaner(sequence): sequence = sequence.replace('[', '') sequence = sequence.replace(']', '') elif type(sequence) is list: - sequence = [value.replace('[', '').replace(']', '') - for value in sequence] - sequence = [value.replace('(', '').replace(')', '') - for value in sequence] + sequence = [ value.replace('[', '').replace(']', '') + for value in sequence] + sequence = [ value.replace('(', '').replace(')', '') + for value in sequence] sequence = [ False if value == 'false' else value for value in sequence ] sequence = [ True if value == 'true' else value @@ -262,7 +262,7 @@ def joinpath(head, *tail): Join two or more pathname components, inserting '/' as needed. If any component is an absolute path, all previous path components will be - discarded. The second argument may be string or list of strings.''' + discarded.''' newtail = list() for item in tail: newtail += [item] @@ -356,36 +356,48 @@ def symlink_relative(src, dest): copyfile2(cp_src, dest) -def link_relative(src, dest): - '''Like ln -s, except that src is given relative to the current directory - (or absolute), not given relative to the directory of dest.''' +def as_link_value_at_dest(src, dest): + '''Compute the symbolic link value to place at dest, such that the + resulting symbolic link points to src. src is given relative to the + current directory (or absolute).''' if type(src) is not str: raise TypeError('src must be a string, not %s' % (type(src).__name__)) if type(dest) is not str: raise TypeError('dest must be a string, not %s' % (type(dest).__name__)) if src.startswith('/') or (len(src) >= 2 and src[1] == ':'): - symlink_relative(src, dest) + return src else: # if src is not absolute if dest.startswith('/') or (len(dest) >= 2 and dest[1] == ':'): cwd = os.getcwd() - symlink_relative(joinpath(cwd, src), dest) + return joinpath(cwd, src) else: # if dest is not absolute destdir = os.path.dirname(dest) if not destdir: destdir = '.' - src = relativize(destdir, src) - symlink_relative(src, dest) + return relativize(destdir, src) + + +def link_relative(src, dest): + '''Like ln -s, except that src is given relative to the current directory + (or absolute), not given relative to the directory of dest.''' + if type(src) is not str: + raise TypeError('src must be a string, not %s' % (type(src).__name__)) + if type(dest) is not str: + raise TypeError('dest must be a string, not %s' % (type(dest).__name__)) + link_value = as_link_value_at_dest(src, dest) + symlink_relative(link_value, dest) def link_if_changed(src, dest): '''Create a symlink, but avoids munging timestamps if the link is correct.''' - ln_target = os.path.realpath(src) - if not (os.path.islink(dest) and src == ln_target): + link_value = as_link_value_at_dest(src, dest) + if not (os.path.islink(dest) and os.readlink(dest) == link_value): try: os.remove(dest) except FileNotFoundError: pass - link_relative(src, dest) + # Equivalent to link_relative(src, dest): + symlink_relative(link_value, dest) def filter_filelist(separator, filelist, -- 2.34.1