Add safety check for local --remove-source-files.
[rsync.git] / packaging / release-rsync
index 05ec577a48ad5a3600eacfe2e477bf5cf631f1c8..f37bd18422e25fe60a8375d9bff9e4682bb23c95 100755 (executable)
@@ -18,6 +18,9 @@ dest = os.environ['HOME'] + '/samba-rsync-ftp'
 ORIGINAL_PATH = os.environ['PATH']
 
 def main():
+    if not os.path.isfile('packaging/release-rsync'):
+        die('You must run this script from the top of your rsync checkout.')
+
     now = datetime.now()
     cl_today = now.strftime('* %a %b %d %Y')
     year = now.strftime('%Y')
@@ -30,7 +33,7 @@ def main():
 
     signal.signal(signal.SIGINT, signal_handler)
 
-    if cmd_txt_chk(['packaging/prep-auto-dir']) == '':
+    if cmd_txt_chk(['packaging/prep-auto-dir']).out == '':
         die('You must setup an auto-build-save dir to use this script.');
 
     auto_dir, gen_files = get_gen_files(True)
@@ -44,6 +47,17 @@ def main():
 {dash_line}
 """)
 
+    with open('build/rsync.1') as fh:
+        for line in fh:
+            if line.startswith(r'.\" prefix='):
+                doc_prefix = line.split('=')[1].strip()
+                if doc_prefix != '/usr':
+                    warn(f"*** The documentation was built with prefix {doc_prefix} instead of /usr ***")
+                    die("*** Read the md2man script for a way to override this. ***")
+                break
+            if line.startswith('.P'):
+                die("Failed to find the prefix comment at the start of the rsync.1 manpage.")
+
     if not os.path.isdir(dest):
         die(dest, "dest does not exist")
     if not os.path.isdir('.git'):
@@ -60,7 +74,7 @@ def main():
     curversion = get_rsync_version()
 
     # All version values are strings!
-    lastversion, last_protocol_version = get_NEWS_version_info()
+    lastversion, last_protocol_version, pdate = get_NEWS_version_info()
     protocol_version, subprotocol_version = get_protocol_versions()
 
     version = curversion
@@ -84,7 +98,7 @@ def main():
     if os.path.lexists(rsync_ver):
         die(f'"{rsync_ver}" must not exist in the current directory.')
 
-    out = cmd_txt_chk(['git', 'tag', '-l', v_ver])
+    out = cmd_txt_chk(['git', 'tag', '-l', v_ver]).out
     if out != '':
         print(f"Tag {v_ver} already exists.")
         ans = input("\nDelete tag or quit? [Q/del] ")
@@ -116,11 +130,8 @@ def main():
         release += '.' + pre
 
     finalversion = re.sub(r'pre\d+', '', version)
-    if protocol_version == last_protocol_version:
-        proto_changed = 'unchanged'
-        proto_change_date = ' ' * 11
-    else:
-        proto_changed = 'changed'
+    proto_changed = protocol_version != last_protocol_version
+    if proto_changed:
         if finalversion in pdate:
             proto_change_date = pdate[finalversion]
         else:
@@ -129,6 +140,8 @@ def main():
                 if re.match(r'^\d\d \w\w\w \d\d\d\d$', ans):
                     break
             proto_change_date = ans
+    else:
+        proto_change_date = ' ' * 11
 
     if 'pre' in lastversion:
         if not pre:
@@ -180,7 +193,9 @@ About to:
         with open(fn, 'r', encoding='utf-8') as fh:
             old_txt = txt = fh.read()
         if fn == 'version.h':
-            txt = f'#define RSYNC_VERSION "{version}"\n'
+            x_re = re.compile(r'^(#define RSYNC_VERSION).*', re.M)
+            msg = f"Unable to update RSYNC_VERSION in {fn}"
+            txt = replace_or_die(x_re, r'\1 "%s"' % version, txt, msg)
         elif '.spec' in fn:
             for var, val in specvars.items():
                 x_re = re.compile(r'^%s .*' % re.escape(var), re.M)
@@ -189,14 +204,17 @@ About to:
             txt = replace_or_die(x_re, r'%s \1' % cl_today, txt, f"Unable to update ChangeLog header in {fn}")
         elif fn == 'rsync.h':
             x_re = re.compile('(#define\s+SUBPROTOCOL_VERSION)\s+(\d+)')
-            repl = lambda m: m[1] + ' ' + '0' if not pre or proto_changed != 'changed' else 1 if m[2] == '0' else m[2]
+            repl = lambda m: m[1] + ' ' + ('0' if not pre or not proto_changed else '1' if m[2] == '0' else m[2])
             txt = replace_or_die(x_re, repl, txt, f"Unable to find SUBPROTOCOL_VERSION define in {fn}")
         elif fn == 'NEWS.md':
             efv = re.escape(finalversion)
-            x_re = re.compile(r'^<.+>\s+# NEWS for rsync %s \(UNRELEASED\)\s+Protocol: .+\n' % efv)
+            x_re = re.compile(r'^# NEWS for rsync %s \(UNRELEASED\)\s+## Changes in this version:\n' % efv
+                    + r'(\n### PROTOCOL NUMBER:\s+- The protocol number was changed to \d+\.\n)?')
             rel_day = 'UNRELEASED' if pre else today
-            repl = (f'<a name="{finalversion}"></a>\n\n# NEWS for rsync {finalversion} ({rel_day})\n\n'
-                + f"Protocol: {protocol_version} ({proto_changed})\n")
+            repl = (f'# NEWS for rsync {finalversion} ({rel_day})\n\n'
+                + '## Changes in this version:\n')
+            if proto_changed:
+                repl += f'\n### PROTOCOL NUMBER:\n\n - The protocol number was changed to {protocol_version}.\n'
             good_top = re.sub(r'\(.*?\)', '(UNRELEASED)', repl, 1)
             msg = f"The top lines of {fn} are not in the right format.  It should be:\n" + good_top
             txt = replace_or_die(x_re, repl, txt, msg)
@@ -214,7 +232,7 @@ About to:
     cmd_chk(['packaging/year-tweak'])
 
     print(dash_line)
-    cmd_run("git diff --color | less -p '^diff .*'")
+    cmd_run("git diff".split())
 
     srctar_name = f"{rsync_ver}.tar.gz"
     pattar_name = f"rsync-patches-{version}.tar.gz"
@@ -229,10 +247,10 @@ About to:
 
 About to:
     - git commit all changes
-    - generate the manpages
+    - run a full build, ensuring that the manpages & configure.sh are up-to-date
     - merge the {args.master_branch} branch into the patch/{args.master_branch}/* branches
-    - update the files in the "patches" dir and OPTIONALLY
-      (if you type 'y') to launch a shell for each patch
+    - update the files in the "patches" dir and OPTIONALLY (if you type 'y') to
+      run patch-update with the --make option (which opens a shell on error)
 """)
     ans = input("<Press Enter OR 'y' to continue> ")
 
@@ -240,9 +258,9 @@ About to:
     if s.returncode:
         die('Aborting')
 
-    cmd_chk('make gen')
+    cmd_chk('touch configure.ac && packaging/smart-make && make gen')
 
-    print(f'Creating any missing patch branches.')
+    print('Creating any missing patch branches.')
     s = cmd_run(f'packaging/branch-from-patch --branch={args.master_branch} --add-missing')
     if s.returncode:
         die('Aborting')
@@ -253,8 +271,8 @@ About to:
         die('Aborting')
 
     if re.match(r'^y', ans, re.I):
-        print(f'\nVisiting all "patch/{args.master_branch}/*" branches ...')
-        cmd_run(f"packaging/patch-update --branch={args.master_branch} --skip-check --shell")
+        print(f'\nRunning smart-make on all "patch/{args.master_branch}/*" branches ...')
+        cmd_run(f"packaging/patch-update --branch={args.master_branch} --skip-check --make")
 
     if os.path.isdir('patches/.git'):
         s = cmd_run(f"cd patches && git commit -a -m 'The patches for {version}.'")
@@ -280,13 +298,13 @@ About to:
     # TODO: is there a better way to ensure that our passphrase is in the agent?
     cmd_run("touch TeMp; gpg --sign TeMp; rm TeMp*")
 
-    out = cmd_txt(f"git tag -s -m 'Version {version}.' {v_ver}", capture='combined')
+    out = cmd_txt(f"git tag -s -m 'Version {version}.' {v_ver}", capture='combined').out
     print(out, end='')
     if 'bad passphrase' in out or 'failed' in out:
         die('Aborting')
 
     if os.path.isdir('patches/.git'):
-        out = cmd_txt(f"cd patches && git tag -s -m 'Version {version}.' {v_ver}", capture='combined')
+        out = cmd_txt(f"cd patches && git tag -s -m 'Version {version}.' {v_ver}", capture='combined').out
         print(out, end='')
         if 'bad passphrase' in out or 'failed' in out:
             die('Aborting')
@@ -322,10 +340,10 @@ About to:
     shutil.rmtree(rsync_ver)
 
     print(f"Updating the other files in {dest} ...")
-    md_files = 'README.md NEWS.md'.split()
+    md_files = 'README.md NEWS.md INSTALL.md'.split()
     html_files = [ fn for fn in gen_pathnames if fn.endswith('.html') ]
     cmd_chk(['rsync', '-a', *md_files, *html_files, dest])
-    cmd_chk(["packaging/md2html"] + [ dest +'/'+ fn for fn in md_files ])
+    cmd_chk(["./md-convert", "--dest", dest, *md_files])
 
     cmd_chk(f"git log --name-status | gzip -9 >{dest}/ChangeLog.gz")