tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

update_versions.py (3864B)


      1 #!/usr/bin/env python
      2 
      3 # Future imports for Python 2.7, mandatory in 3.0
      4 from __future__ import division
      5 from __future__ import print_function
      6 from __future__ import unicode_literals
      7 
      8 import io
      9 import os
     10 import re
     11 import sys
     12 import time
     13 
     14 def P(path):
     15    """
     16    Give 'path' as a path relative to the abs_top_srcdir environment
     17    variable.
     18    """
     19    return os.path.join(
     20        os.environ.get('abs_top_srcdir', "."),
     21        path)
     22 
     23 def warn(msg):
     24    """
     25    Print an warning message.
     26    """
     27    print("WARNING: {}".format(msg), file=sys.stderr)
     28 
     29 def find_version(infile):
     30    """
     31    Given an open file (or some other iterator of lines) holding a
     32    configure.ac file, find the current version line.
     33    """
     34    for line in infile:
     35        m = re.search(r'AC_INIT\(\[tor\],\s*\[([^\]]*)\]\)', line)
     36        if m:
     37            return m.group(1)
     38 
     39    return None
     40 
     41 def update_version_in(infile, outfile, regex, versionline):
     42    """
     43    Copy every line from infile to outfile. If any line matches 'regex',
     44    replace it with 'versionline'.  Return True if any line was changed;
     45    false otherwise.
     46 
     47    'versionline' is either a string -- in which case it is used literally,
     48    or a function that receives the output of 'regex.match'.
     49    """
     50    found = False
     51    have_changed = False
     52    for line in infile:
     53        m = regex.match(line)
     54        if m:
     55            found = True
     56            oldline = line
     57            if type(versionline) == type(u""):
     58                line = versionline
     59            else:
     60                line = versionline(m)
     61            if not line.endswith("\n"):
     62                line += "\n"
     63            if oldline != line:
     64                have_changed = True
     65        outfile.write(line)
     66 
     67    if not found:
     68        warn("didn't find any version line to replace in {}".format(infile.name))
     69 
     70    return have_changed
     71 
     72 def replace_on_change(fname, change):
     73    """
     74    If "change" is true, replace fname with fname.tmp.  Otherwise,
     75    delete fname.tmp.  Log what we're doing to stderr.
     76    """
     77    if not change:
     78        print("No change in {}".format(fname))
     79        os.unlink(fname+".tmp")
     80    else:
     81        print("Updating {}".format(fname))
     82        os.rename(fname+".tmp", fname)
     83 
     84 
     85 def update_file(fname,
     86                regex,
     87                versionline,
     88                encoding="utf-8"):
     89    """
     90    Replace any line matching 'regex' in 'fname' with 'versionline'.
     91    Do not modify 'fname' if there are no changes made.  Use the
     92    provided encoding to read and write.
     93    """
     94    with io.open(fname, "r", encoding=encoding) as f, \
     95         io.open(fname+".tmp", "w", encoding=encoding) as outf:
     96        have_changed = update_version_in(f, outf, regex, versionline)
     97 
     98    replace_on_change(fname, have_changed)
     99 
    100 # Find out our version
    101 with open(P("configure.ac")) as f:
    102    version = find_version(f)
    103 
    104 # If we have no version, we can't proceed.
    105 if version == None:
    106    print("No version found in configure.ac", file=sys.stderr())
    107    sys.exit(1)
    108 
    109 print("The version is {}".format(version))
    110 
    111 today = time.strftime("%Y-%m-%d", time.gmtime())
    112 
    113 # In configure.ac, we replace the definition of APPROX_RELEASE_DATE
    114 # with "{today} for {version}", but only if the version does not match
    115 # what is already there.
    116 def replace_fn(m):
    117    if m.group(1) != version:
    118        # The version changed -- we change the date.
    119        return u'AC_DEFINE(APPROX_RELEASE_DATE, ["{}"], # for {}'.format(today, version)
    120    else:
    121        # No changes.
    122        return m.group(0)
    123 update_file(P("configure.ac"),
    124            re.compile(r'AC_DEFINE\(APPROX_RELEASE_DATE.* for (.*)'),
    125            replace_fn)
    126 
    127 # In tor-mingw.nsi.in, we replace the definition of VERSION.
    128 update_file(P("contrib/win32build/tor-mingw.nsi.in"),
    129            re.compile(r'!define VERSION .*'),
    130            u'!define VERSION "{}"'.format(version),
    131            encoding="iso-8859-1")