Merge remote-tracking branch 'github/prop297'

This commit is contained in:
Nick Mathewson 2018-12-11 09:44:57 -05:00
commit b915b6cd21
9 changed files with 176 additions and 67 deletions

View File

@ -418,7 +418,7 @@ endif
.PHONY: update-versions
update-versions:
$(PERL) $(top_builddir)/scripts/maint/updateVersions.pl
abs_top_srcdir="$(abs_top_srcdir)" $(PYTHON) $(top_srcdir)/scripts/maint/update_versions.py
.PHONY: callgraph
callgraph:

7
changes/prop297 Normal file
View File

@ -0,0 +1,7 @@
o Minor features (required protocols):
- Tor no longer exits if it is missing a required protocol, if the
consensus that requires the protocol predates the release date of the
version of Tor. This change prevents Tor releases from exiting because
of an old cached consensus, on the theory that a newer cached
consensus might not require the protocol. Implements proposal 297;
closes ticket 27735.

View File

@ -8,6 +8,15 @@ AC_INIT([tor],[0.4.0.0-alpha-dev])
AC_CONFIG_SRCDIR([src/app/main/tor_main.c])
AC_CONFIG_MACRO_DIR([m4])
# DO NOT EDIT THIS DEFINITION BY HAND UNLESS YOU KNOW WHAT YOU'RE DOING.
#
# The update_versions.py script updates this definition when the
# version number changes. Tor uses it to make sure that it
# only shuts down for missing "required protocols" when those protocols
# are listed as required by a consensus after this date.
AC_DEFINE(APPROX_RELEASE_DATE, ["2019-01-15"], # for 0.4.0.0-alpha-dev
[Approximate date when this software was released. (Updated when the version changes.)])
# "foreign" means we don't follow GNU package layout standards
# "1.11" means we require automake version 1.11 or newer
# "subdir-objects" means put .o files in the same directory as the .c files
@ -2417,7 +2426,6 @@ AC_CONFIG_FILES([
src/config/torrc.minimal
src/rust/.cargo/config
scripts/maint/checkOptionDocs.pl
scripts/maint/updateVersions.pl
])
if test "x$asciidoc" = "xtrue" && test "$ASCIIDOC" = "none"; then

View File

@ -135,13 +135,9 @@ new Tor release:
=== III. Making the source release.
1. In `maint-0.?.x`, bump the version number in `configure.ac` and run
`perl scripts/maint/updateVersions.pl` to update version numbers in other
`make update-versions` to update version numbers in other
places, and commit. Then merge `maint-0.?.x` into `release-0.?.x`.
(NOTE: To bump the version number, edit `configure.ac`, and then run
either `make`, or `perl scripts/maint/updateVersions.pl`, depending on
your version.)
When you merge the maint branch forward to the next maint branch, or into
master, merge it with "-s ours" to avoid a needless version bump.

View File

@ -1,59 +0,0 @@
#!/usr/bin/perl -w
$CONFIGURE_IN = '@abs_top_srcdir@/configure.ac';
$ORCONFIG_H = '@abs_top_srcdir@/src/win32/orconfig.h';
$TOR_NSI = '@abs_top_srcdir@/contrib/win32build/tor-mingw.nsi.in';
$quiet = 1;
sub demand {
my $fn = shift;
die "Missing file $fn" unless (-f $fn);
}
demand($CONFIGURE_IN);
demand($ORCONFIG_H);
demand($TOR_NSI);
# extract version from configure.ac
open(F, $CONFIGURE_IN) or die "$!";
$version = undef;
while (<F>) {
if (/AC_INIT\(\[tor\],\s*\[([^\]]*)\]\)/) {
$version = $1;
last;
}
}
die "No version found" unless $version;
print "Tor version is $version\n" unless $quiet;
close F;
sub correctversion {
my ($fn, $defchar) = @_;
undef $/;
open(F, $fn) or die "$!";
my $s = <F>;
close F;
if ($s =~ /^$defchar(?:)define\s+VERSION\s+\"([^\"]+)\"/m) {
$oldver = $1;
if ($oldver ne $version) {
print "Version mismatch in $fn: It thinks that the version is $oldver. I think it's $version. Fixing.\n";
$line = $defchar . "define VERSION \"$version\"";
open(F, ">$fn.bak");
print F $s;
close F;
$s =~ s/^$defchar(?:)define\s+VERSION.*?$/$line/m;
open(F, ">$fn");
print F $s;
close F;
} else {
print "$fn has the correct version. Good.\n" unless $quiet;
}
} else {
print "Didn't find a version line in $fn -- uh oh.\n";
}
}
correctversion($TOR_NSI, "!");
correctversion($ORCONFIG_H, "#");

133
scripts/maint/update_versions.py Executable file
View File

@ -0,0 +1,133 @@
#!/usr/bin/env python
from __future__ import print_function
import io
import os
import re
import sys
import time
def P(path):
"""
Give 'path' as a path relative to the abs_top_srcdir environment
variable.
"""
return os.path.join(
os.environ.get('abs_top_srcdir', "."),
path)
def warn(msg):
"""
Print an warning message.
"""
print("WARNING: {}".format(msg), file=sys.stderr)
def find_version(infile):
"""
Given an open file (or some other iterator of lines) holding a
configure.ac file, find the current version line.
"""
for line in infile:
m = re.search(r'AC_INIT\(\[tor\],\s*\[([^\]]*)\]\)', line)
if m:
return m.group(1)
return None
def update_version_in(infile, outfile, regex, versionline):
"""
Copy every line from infile to outfile. If any line matches 'regex',
replace it with 'versionline'. Return True if any line was changed;
false otherwise.
'versionline' is either a string -- in which case it is used literally,
or a function that receives the output of 'regex.match'.
"""
found = False
have_changed = False
for line in infile:
m = regex.match(line)
if m:
found = True
oldline = line
if type(versionline) == type(u""):
line = versionline
else:
line = versionline(m)
if not line.endswith("\n"):
line += "\n"
if oldline != line:
have_changed = True
outfile.write(line)
if not found:
warn("didn't find any version line to replace in {}".format(infile.name))
return have_changed
def replace_on_change(fname, change):
"""
If "change" is true, replace fname with fname.tmp. Otherwise,
delete fname.tmp. Log what we're doing to stderr.
"""
if not change:
print("No change in {}".format(fname))
os.unlink(fname+".tmp")
else:
print("Updating {}".format(fname))
os.rename(fname+".tmp", fname)
def update_file(fname,
regex,
versionline,
encoding="utf-8"):
"""
Replace any line matching 'regex' in 'fname' with 'versionline'.
Do not modify 'fname' if there are no changes made. Use the
provided encoding to read and write.
"""
with io.open(fname, "r", encoding=encoding) as f, \
io.open(fname+".tmp", "w", encoding=encoding) as outf:
have_changed = update_version_in(f, outf, regex, versionline)
replace_on_change(fname, have_changed)
# Find out our version
with open("configure.ac") as f:
version = find_version(f)
# If we have no version, we can't proceed.
if version == None:
print("No version found in configure.ac", file=sys.stderr())
sys.exit(1)
print("The version is {}".format(version))
today = time.strftime("%Y-%m-%d", time.gmtime())
# In configure.ac, we replace the definition of APPROX_RELEASE_DATE
# with "{today} for {version}", but only if the version does not match
# what is already there.
def replace_fn(m):
if m.group(1) != version:
# The version changed -- we change the date.
return u'AC_DEFINE(APPROX_RELEASE_DATE, ["{}"], # for {}'.format(today, version)
else:
# No changes.
return m.group(0)
update_file(P("configure.ac"),
re.compile(r'AC_DEFINE\(APPROX_RELEASE_DATE.* for (.*)'),
replace_fn)
# In tor-mingw.nsi.in, we replace the definition of VERSION.
update_file(P("contrib/win32build/tor-mingw.nsi.in"),
re.compile(r'!define VERSION .*'),
u'!define VERSION "{}"'.format(version),
encoding="iso-8859-1")
# In src/win32/orconfig.h, we replace the definition of VERSION.
update_file(P("src/win32/orconfig.h"),
re.compile(r'#define VERSION .*'),
u'#define VERSION "{}"'.format(version))

View File

@ -16,6 +16,25 @@
#include "core/or/tor_version_st.h"
/**
* Return the approximate date when this release came out, or was
* scheduled to come out, according to the APPROX_RELEASE_DATE set in
* configure.ac
**/
time_t
tor_get_approx_release_date(void)
{
char tbuf[ISO_TIME_LEN+1];
tor_snprintf(tbuf, sizeof(tbuf),
"%s 00:00:00", APPROX_RELEASE_DATE);
time_t result = 0;
int r = parse_iso_time(tbuf, &result);
if (BUG(r < 0)) {
result = 0;
}
return result;
}
/** Return VS_RECOMMENDED if <b>myversion</b> is contained in
* <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
* entries. Else, return VS_OLD if every member of

View File

@ -26,6 +26,8 @@ typedef enum version_status_t {
VS_UNKNOWN, /**< We have no idea. */
} version_status_t;
time_t tor_get_approx_release_date(void);
version_status_t tor_version_is_obsolete(const char *myversion,
const char *versionlist);
int tor_version_parse_platform(const char *platform,

View File

@ -2681,6 +2681,9 @@ networkstatus_check_required_protocols(const networkstatus_t *ns,
const char *required, *recommended;
char *missing = NULL;
const bool consensus_postdates_this_release =
ns->valid_after >= tor_get_approx_release_date();
tor_assert(warning_out);
if (client_mode) {
@ -2698,7 +2701,7 @@ networkstatus_check_required_protocols(const networkstatus_t *ns,
"%s on the Tor network. The missing protocols are: %s",
func, missing);
tor_free(missing);
return 1;
return consensus_postdates_this_release ? 1 : 0;
}
if (! protover_all_supported(recommended, &missing)) {