From aa9451e5447a63c9e383328c174b8612f8fad502 Mon Sep 17 00:00:00 2001 From: Nick Rhodes Date: Sun, 19 Jan 2020 02:08:27 +0000 Subject: [PATCH 1/7] Move running process check into dataGather method Check and store running processes in self.procs_out to save running 'ps' each time we need to check for process. Files can just be checked with os.path.exists instead of a dedicated function. --- configsnap | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/configsnap b/configsnap index bea1296..5957fd5 100755 --- a/configsnap +++ b/configsnap @@ -158,13 +158,15 @@ def compare_files(): 'dnf.conf', 'pcs_constraints', 'sudoers'] # Add php files if detected - if is_php_detected: + if os.path.exists('/usr/bin/php'): compare_files.append('php.ini') + compare_files.append('php_modules') + compare_files.append('php_info') if os.path.exists('/usr/bin/pecl'): compare_files.append('pecl-list') # Add apache files if detected - if is_apache_detected: + if run.is_running('/usr/sbin/httpd', '/usr/sbin/httpd.worker'): compare_files.append('httpd_modules') compare_files.append('httpd_vhosts') @@ -408,9 +410,30 @@ class dataGather: if diffs_found_msg is False: report_info("No differences found for files in %s" % sdir) + def is_running(self, *paths): + if len(self.procs_out) == 0: + # Get a list of processes running on the server + procs = subprocess.Popen( + ['ps', '-A', '--noheaders', '-o', 'args'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + procs_out, procs_err = procs.communicate() + if procs.returncode == 0: + self.procs_out = [x.split()[0] for x in procs_out.splitlines()] + else: + report_error('Failed to get process list') + + for path in paths: + if path in self.procs_out: + return True + + return False + + def __init__(self, workdir, phase): self.workdir = workdir self.phase = phase + self.procs_out = [] ################################################### @@ -548,19 +571,6 @@ for section in Config.sections(): report_error("Wrong \"Type\" defined for custom collection entry \"%s\"; " "should be \"file\", \"directory\" or \"command\"" % section) -# Get a list of processes running on the server -procs = subprocess.Popen( - ['ps', '-A', '--noheaders', '-o', 'args'], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - -procs_output = procs.communicate()[0] -if procs.returncode != 0: - report_error('Failed to get process list') - -# Just keep the process name, drop the arguments -procs_output = procs_output.splitlines() -procs_output = [x.split()[0] for x in procs_output] - run = dataGather(workdir, phase) report_info("Getting storage details (LVM, partitions, multipathing)...") if os.path.exists('/sbin/lvs'): @@ -717,15 +727,14 @@ if os.path.exists(hpasmpath): break break -if '/usr/sbin/httpd' in procs_output or '/usr/sbin/httpd.worker' in procs_output: +if run.is_running('/usr/sbin/httpd', '/usr/sbin/httpd.worker'): report_info("Getting Apache vhosts and modules...") - is_apache_detected = True run.run_command( ['httpd', '-S'], 'httpd_vhosts', fail_ok=False, sort=False) run.run_command( ['httpd', '-M'], 'httpd_modules', fail_ok=False, sort=True) -if '/usr/libexec/mysqld' in procs_output: +if run.is_running('/usr/libexec/mysqld'): report_info("Getting MySQL databases...") run.run_command(['mysql', '-Bse', 'show databases;'], 'mysql_databases', fail_ok=True, sort=True) @@ -824,7 +833,6 @@ report_info("\n") # php specifics if os.path.exists('/usr/bin/php'): - is_php_detected = True report_info("Copying PHP related files...") run.copy_file('/etc/php.ini', fail_ok=True) if os.path.exists('/etc/php.d'): From cfadd93dc81796414175b409f6cb139d6e352ee0 Mon Sep 17 00:00:00 2001 From: Nick Rhodes Date: Sun, 19 Jan 2020 02:15:29 +0000 Subject: [PATCH 2/7] Resolve flake8 test --- configsnap | 1 - 1 file changed, 1 deletion(-) diff --git a/configsnap b/configsnap index 5957fd5..267166c 100755 --- a/configsnap +++ b/configsnap @@ -429,7 +429,6 @@ class dataGather: return False - def __init__(self, workdir, phase): self.workdir = workdir self.phase = phase From abcdbfa7da27d0f029604b668a476f4cee411016 Mon Sep 17 00:00:00 2001 From: Jean M Date: Tue, 21 Jan 2020 15:30:57 +0000 Subject: [PATCH 3/7] changing paradigm to select which files to compare, should allow better integration of additional checks. Added /usr/sbin/mysql for mysql detection. Still WIP --- configsnap | 201 ++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 103 deletions(-) diff --git a/configsnap b/configsnap index 267166c..b235a02 100755 --- a/configsnap +++ b/configsnap @@ -25,8 +25,7 @@ import re import tarfile -version = "0.17.1" -diffs_found_msg = False +version = "0.18.1" is_php_detected = False is_apache_detected = False @@ -50,7 +49,6 @@ def report_error(message): if not options.silent_enabled: sys.stdout.write("\033[91m%s\n\033[0m" % message) - def check_option_conflicts(options): # Do not allow silent and verbose options to be used in conjunction if options.silent_enabled is True and options.verbose_enabled is True: @@ -128,100 +126,92 @@ def create_archive(tagdir, workdir, tag, overwrite): return output_filename, True -def compare_files(): - # Check that there are pre files, and exit if there aren't - found_pre = False +def compare_files(options): + global diffs_found + diffs_found = False + ## Check that there are pre files, and exit if there aren't + #found_pre = False run = dataGather(workdir, phase) - for filename in os.listdir(workdir): - if filename.endswith(options.pre_suffix): - found_pre = True - if not found_pre: - report_error("Unable to diff, as no " + - options.pre_suffix + " pre files") - sys.exit(0) - - report_info("\nThis is %s phase so performing file diffs..." % phase) - - if 'rollback' in phase: - run.get_diff_files('packages') - - compare_files = ['sysvinit', 'mounts', 'netstat', 'ip_addresses', - 'network', 'interfaces', 'hosts', 'lvs', 'pvs', 'vgs', - 'fstab', 'powermt', 'omreport_version', 'ip_routes', - 'partitions', 'lspci', 'omreport_memory', - 'omreport_processors', 'omreport_nics', 'omreport_vdisk', - 'omreport_pdisk', 'hpreport_server', 'hpreport_memory', - 'hpreport_bios', 'hpreport_storage_controller', - 'hpreport_storage_vdisk', 'hpreport_storage_pdisk', - 'multipath', 'systemdinit', 'upstartinit', 'yum.conf', - 'dnf.conf', 'pcs_constraints', 'sudoers'] - - # Add php files if detected - if os.path.exists('/usr/bin/php'): - compare_files.append('php.ini') - compare_files.append('php_modules') - compare_files.append('php_info') - if os.path.exists('/usr/bin/pecl'): - compare_files.append('pecl-list') - - # Add apache files if detected - if run.is_running('/usr/sbin/httpd', '/usr/sbin/httpd.worker'): - compare_files.append('httpd_modules') - compare_files.append('httpd_vhosts') - - # Array to hold custom collection files and commands to compare - additional_to_compare = [] - for section in Config.sections(): - try: - if Config.has_option(section, 'compare') and Config.get(section, 'compare').lower() == "true": - additional_to_compare.append(section) - except ConfigParser.NoOptionError, e: - report_error( - "Check config file options for section %s: %s" % (section, e)) - except Exception, e: - report_error( - "Could not parse config file section %s: %s" % (section, e)) + # Collects all files and dir at the top level + all_files = os.listdir(workdir) - compare_files.extend(additional_to_compare) + # Proceed if at least one file with options.pre_suffix is present + if any(filename.endswith(".%s" % options.pre_suffix) for filename in all_files): + report_info("\nThis is %s phase so performing file diffs..." % phase) - for filename in compare_files: - pre_filename = os.path.join(workdir, - "%s.%s" % (filename, options.pre_suffix)) - if os.path.exists(pre_filename): - run.get_diff_files(filename) + if 'rollback' in phase: + run.get_diff_files('packages', options) - # Report subdirectories at the subdir level unless ther verbose option is - # given, in which case report as usual - report_info("\nStarting sub-dir diffs...") - for directory in os.listdir(workdir): - if os.path.isdir(os.path.join(workdir, directory)): - run.get_diff_dir(directory) + # to search for files with pre_suffix or phase only + suffix_exist = re.compile('\.(' + options.pre_suffix + '|' + options.phase + ')$') + filtered_files = [] + for index, value in enumerate(all_files): + if suffix_exist.search(value): + filtered_files.append(suffix_exist.sub('', value)) - try: - uname_pre_fd = open( - os.path.join(workdir, 'uname.' + options.pre_suffix), 'r') - uname_post_fd = open( - os.path.join(workdir, "uname.%s" % phase), 'r') - uname_pre = uname_pre_fd.read().strip() - uname_post = uname_post_fd.read().strip() - if uname_pre != uname_post: - sys.stdout.write("Old uname: %s. New uname: %s\n" % - (uname_pre, uname_post)) - except Exception, e: - report_error( - "Unable to open file %s: %s" % ((e.filename, e.strerror))) + compare_files = list(set(filtered_files)) + compare_files.sort() + +## TODO: TEST if still required + # Array to hold custom collection files and commands to compare + additional_to_compare = [] + for section in Config.sections(): + try: + if Config.has_option(section, 'compare') and Config.get(section, 'compare').lower() == "true": + additional_to_compare.append(section) + except ConfigParser.NoOptionError, e: + report_error( + "Check config file options for section %s: %s" % (section, e)) + except Exception, e: + report_error( + "Could not parse config file section %s: %s" % (section, e)) + + compare_files.extend(additional_to_compare) + + for filename in compare_files: + pre_filename = os.path.join(workdir, + "%s.%s" % (filename, options.pre_suffix)) + if os.path.exists(pre_filename): + run.get_diff_files(filename, options) + + # Report subdirectories at the subdir level unless ther verbose option is + # given, in which case report as usual + report_info("\nStarting sub-dir diffs...") + for directory in os.listdir(workdir): + if os.path.isdir(os.path.join(workdir, directory)): + run.get_diff_dir(directory, options) + + try: + uname_pre_fd = open( + os.path.join(workdir, 'uname.' + options.pre_suffix), 'r') + uname_post_fd = open( + os.path.join(workdir, "uname.%s" % phase), 'r') + uname_pre = uname_pre_fd.read().strip() + uname_post = uname_post_fd.read().strip() + if uname_pre != uname_post: + sys.stdout.write("Old uname: %s. New uname: %s\n" % + (uname_pre, uname_post)) + except Exception, e: + report_error( + "Unable to open file %s: %s" % ((e.filename, e.strerror))) + + if diffs_found: + report_info_blue("\nINTERPRETING DIFFS:\n") + report_info_blue("* Lines beginning with a - show an " + "entry from the " + options.pre_suffix + " pre file " + "which has changed\n" "or which is not present in the .post or .rollback file.\n") + report_info_blue("* Lines beginning with a + show an entry from the " + ".post or.rollback file which\nhas changed or which " + "is not present in the " + options.pre_suffix + " pre file.\n") + report_info_blue("Please review all diff output above carefully and " + "account for any differences\nfound.\n") + + else: + report_error("Unable to diff, as no " + + options.pre_suffix + " pre files") + sys.exit(1) - if diffs_found_msg: - report_info_blue("\nINTERPRETING DIFFS:\n") - report_info_blue("* Lines beginning with a - show an " - "entry from the " + options.pre_suffix + " pre file " - "which has changed\n" "or which is not present in the .post or .rollback file.\n") - report_info_blue("* Lines beginning with a + show an entry from the " - ".post or.rollback file which\nhas changed or which " - "is not present in the " + options.pre_suffix + " pre file.\n") - report_info_blue("Please review all diff output above carefully and " - "account for any differences\nfound.\n") class dataGather: @@ -329,8 +319,8 @@ class dataGather: report_error("Unable to open %s: %s" % (filename, e.strerror)) return False - def get_diff_files(self, filename): - global diffs_found_msg + + def get_diff_files(self, filename, options): filename = os.path.join(self.workdir, filename) pre_filename = "%s.%s" % (filename, options.pre_suffix) post_filename = "%s.%s" % (filename, self.phase) @@ -352,16 +342,18 @@ class dataGather: diff_stdout, diff_stderr = diff_proc.communicate(input=None) if diff_proc.returncode != 0: - diffs_found_msg = True + diffs_found = True report_error( "Differences found against %s.%s:\n" % (filename, options.pre_suffix)) - sys.stdout.writelines(diff_stdout) + if diff_stdout != "": + sys.stdout.writelines(diff_stdout) + else: + report_error(diff_stderr) else: report_info("No differences against %s.%s" % (filename, options.pre_suffix)) - def get_diff_dir(self, sdir): - diffs_found_msg = False + def get_diff_dir(self, sdir, options): all_pre_files = [] sdir = os.path.join(workdir, sdir) @@ -395,20 +387,21 @@ class dataGather: return None if diff_proc.wait() != 0: - diffs_found_msg = True + diffs_found = True report_error("Differences found against %s:\n" % pre_filename) sys.stdout.writelines(diff_proc.stdout.readlines()) elif options.verbose_enabled is True: report_verbose("No differences against %s" % pre_filename) # Looking for new files + local_diffs = False for post_filename in glob.glob(sdir + '/*' + self.phase): if post_filename not in all_pre_files: report_error("+ File added: %s:" % post_filename) - diffs_found_msg = True + local_diffs = True - if diffs_found_msg is False: - report_info("No differences found for files in %s" % sdir) + if local_diffs is False: + report_info("No extra post files found in %s" % sdir) def is_running(self, *paths): if len(self.procs_out) == 0: @@ -560,7 +553,7 @@ else: if options.compare_only: report_info("Comparing files from phases: %s and %s" % (options.pre_suffix, options.phase)) - compare_files() + compare_files(options) sys.exit(0) # Ensure each section has a valid Type @@ -733,10 +726,12 @@ if run.is_running('/usr/sbin/httpd', '/usr/sbin/httpd.worker'): run.run_command( ['httpd', '-M'], 'httpd_modules', fail_ok=False, sort=True) -if run.is_running('/usr/libexec/mysqld'): +if run.is_running('/usr/libexec/mysqld', '/usr/sbin/mysqld'): report_info("Getting MySQL databases...") run.run_command(['mysql', '-Bse', 'show databases;'], 'mysql_databases', fail_ok=True, sort=True) +else: + report_info("No MySQL databases detected (no /usr/libexec/mysqld)") # Run any custom commands for section in Config.sections(): @@ -849,7 +844,7 @@ if os.path.exists('/usr/bin/php'): ['pecl', 'list'], 'pecl-list', fail_ok=True, sort=False) if ('post' in phase or 'rollback' in phase or options.force_compare) and not options.silent_enabled: - compare_files() + compare_files(options) if options.archive_enabled: From 8e44a173932131a764016d21ce677345b255b1f2 Mon Sep 17 00:00:00 2001 From: Jean M Date: Tue, 21 Jan 2020 16:00:02 +0000 Subject: [PATCH 4/7] ready for review --- configsnap | 70 +++++++++++++++++++----------------------------------- 1 file changed, 25 insertions(+), 45 deletions(-) diff --git a/configsnap b/configsnap index b235a02..b3e98eb 100755 --- a/configsnap +++ b/configsnap @@ -24,10 +24,8 @@ import glob import re import tarfile - version = "0.18.1" -is_php_detected = False -is_apache_detected = False +diffs_found = False def report_verbose(message): @@ -127,8 +125,6 @@ def create_archive(tagdir, workdir, tag, overwrite): def compare_files(options): - global diffs_found - diffs_found = False ## Check that there are pre files, and exit if there aren't #found_pre = False run = dataGather(workdir, phase) @@ -138,7 +134,7 @@ def compare_files(options): # Proceed if at least one file with options.pre_suffix is present if any(filename.endswith(".%s" % options.pre_suffix) for filename in all_files): - report_info("\nThis is %s phase so performing file diffs..." % phase) + report_info("Perfoming file diffs...\n") if 'rollback' in phase: run.get_diff_files('packages', options) @@ -153,22 +149,6 @@ def compare_files(options): compare_files = list(set(filtered_files)) compare_files.sort() -## TODO: TEST if still required - # Array to hold custom collection files and commands to compare - additional_to_compare = [] - for section in Config.sections(): - try: - if Config.has_option(section, 'compare') and Config.get(section, 'compare').lower() == "true": - additional_to_compare.append(section) - except ConfigParser.NoOptionError, e: - report_error( - "Check config file options for section %s: %s" % (section, e)) - except Exception, e: - report_error( - "Could not parse config file section %s: %s" % (section, e)) - - compare_files.extend(additional_to_compare) - for filename in compare_files: pre_filename = os.path.join(workdir, "%s.%s" % (filename, options.pre_suffix)) @@ -205,11 +185,11 @@ def compare_files(options): ".post or.rollback file which\nhas changed or which " "is not present in the " + options.pre_suffix + " pre file.\n") report_info_blue("Please review all diff output above carefully and " - "account for any differences\nfound.\n") + "account for any difference found.\n") else: - report_error("Unable to diff, as no " + - options.pre_suffix + " pre files") + report_error("Unable to diff, no files with suffix \"" + + options.pre_suffix + "\" present.") sys.exit(1) @@ -342,6 +322,7 @@ class dataGather: diff_stdout, diff_stderr = diff_proc.communicate(input=None) if diff_proc.returncode != 0: + global diffs_found diffs_found = True report_error( "Differences found against %s.%s:\n" % (filename, options.pre_suffix)) @@ -387,6 +368,7 @@ class dataGather: return None if diff_proc.wait() != 0: + global diffs_found diffs_found = True report_error("Differences found against %s:\n" % pre_filename) sys.stdout.writelines(diff_proc.stdout.readlines()) @@ -730,8 +712,6 @@ if run.is_running('/usr/libexec/mysqld', '/usr/sbin/mysqld'): report_info("Getting MySQL databases...") run.run_command(['mysql', '-Bse', 'show databases;'], 'mysql_databases', fail_ok=True, sort=True) -else: - report_info("No MySQL databases detected (no /usr/libexec/mysqld)") # Run any custom commands for section in Config.sections(): @@ -788,6 +768,24 @@ if os.path.exists('/etc/network/interfaces.d'): if os.path.exists('/etc/sysconfig/network-scripts/'): run.copy_dir('/etc/sysconfig/network-scripts/', file_pattern='(ifcfg-|route-).*', fail_ok=False, sort=False) +# php specifics +if os.path.exists('/usr/bin/php'): + report_info("Copying PHP related files...") + run.copy_file('/etc/php.ini', fail_ok=True) + if os.path.exists('/etc/php.d'): + run.copy_dir('/etc/php.d/', fail_ok=False, sort=False) + + if os.path.exists('/etc/php/'): + run.copy_dir('/etc/php/', fail_ok=False, sort=False) + + run.run_command( + ['php', '-m'], 'php_modules', fail_ok=False, sort=False) + run.run_command( + ['php', '-i'], 'php_info', fail_ok=False, sort=False) + if os.path.exists('/usr/bin/pecl'): + run.run_command( + ['pecl', 'list'], 'pecl-list', fail_ok=True, sort=False) + # copy custom files and directories for section in Config.sections(): @@ -825,24 +823,6 @@ for section in Config.sections(): report_info("\n") -# php specifics -if os.path.exists('/usr/bin/php'): - report_info("Copying PHP related files...") - run.copy_file('/etc/php.ini', fail_ok=True) - if os.path.exists('/etc/php.d'): - run.copy_dir('/etc/php.d/', fail_ok=False, sort=False) - - if os.path.exists('/etc/php/'): - run.copy_dir('/etc/php/', fail_ok=False, sort=False) - - run.run_command( - ['php', '-m'], 'php_modules', fail_ok=False, sort=False) - run.run_command( - ['php', '-i'], 'php_info', fail_ok=False, sort=False) - if os.path.exists('/usr/bin/pecl'): - run.run_command( - ['pecl', 'list'], 'pecl-list', fail_ok=True, sort=False) - if ('post' in phase or 'rollback' in phase or options.force_compare) and not options.silent_enabled: compare_files(options) From 7c617669f32df8ce8bca228c58b1ac1078bbece1 Mon Sep 17 00:00:00 2001 From: Jean M Date: Tue, 21 Jan 2020 17:54:14 +0000 Subject: [PATCH 5/7] flake8 compliant --- configsnap | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/configsnap b/configsnap index b3e98eb..8ffb26d 100755 --- a/configsnap +++ b/configsnap @@ -47,6 +47,7 @@ def report_error(message): if not options.silent_enabled: sys.stdout.write("\033[91m%s\n\033[0m" % message) + def check_option_conflicts(options): # Do not allow silent and verbose options to be used in conjunction if options.silent_enabled is True and options.verbose_enabled is True: @@ -125,8 +126,7 @@ def create_archive(tagdir, workdir, tag, overwrite): def compare_files(options): - ## Check that there are pre files, and exit if there aren't - #found_pre = False + """Compare 2 phases of a same tag""" run = dataGather(workdir, phase) # Collects all files and dir at the top level @@ -140,7 +140,7 @@ def compare_files(options): run.get_diff_files('packages', options) # to search for files with pre_suffix or phase only - suffix_exist = re.compile('\.(' + options.pre_suffix + '|' + options.phase + ')$') + suffix_exist = re.compile('[.](' + options.pre_suffix + '|' + options.phase + ')$') filtered_files = [] for index, value in enumerate(all_files): if suffix_exist.search(value): @@ -193,7 +193,6 @@ def compare_files(options): sys.exit(1) - class dataGather: def copy_file(self, r_filename, destdir=None, fail_ok=False, sort=False): @@ -299,7 +298,6 @@ class dataGather: report_error("Unable to open %s: %s" % (filename, e.strerror)) return False - def get_diff_files(self, filename, options): filename = os.path.join(self.workdir, filename) pre_filename = "%s.%s" % (filename, options.pre_suffix) From c0f63500967daa3ee66af6218702a4b5cdc11979 Mon Sep 17 00:00:00 2001 From: Jean M Date: Wed, 22 Jan 2020 08:44:06 +0000 Subject: [PATCH 6/7] handling comparison exclusions --- configsnap | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/configsnap b/configsnap index 8ffb26d..697666e 100755 --- a/configsnap +++ b/configsnap @@ -24,7 +24,7 @@ import glob import re import tarfile -version = "0.18.1" +version = "0.17.1" diffs_found = False @@ -131,6 +131,8 @@ def compare_files(options): # Collects all files and dir at the top level all_files = os.listdir(workdir) + # Those will always result in positive diffs, this is misleading so we exclude them + exclusions = '^(sysctl|vgcfgbackup[-].*|ps|meminfo|dmesg|crm_mon|pcs_status)$' # Proceed if at least one file with options.pre_suffix is present if any(filename.endswith(".%s" % options.pre_suffix) for filename in all_files): @@ -144,16 +146,15 @@ def compare_files(options): filtered_files = [] for index, value in enumerate(all_files): if suffix_exist.search(value): - filtered_files.append(suffix_exist.sub('', value)) + filebase = suffix_exist.sub('', value) + if not re.match(exclusions, filebase): + filtered_files.append(filebase) compare_files = list(set(filtered_files)) compare_files.sort() for filename in compare_files: - pre_filename = os.path.join(workdir, - "%s.%s" % (filename, options.pre_suffix)) - if os.path.exists(pre_filename): - run.get_diff_files(filename, options) + run.get_diff_files(filename, options) # Report subdirectories at the subdir level unless ther verbose option is # given, in which case report as usual From 846356886780fce7cf77ccb4abd57b49d5a48d76 Mon Sep 17 00:00:00 2001 From: Nick Rhodes Date: Mon, 3 Feb 2020 18:30:11 +0000 Subject: [PATCH 7/7] Release 0.18.0 --- configsnap.spec | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configsnap.spec b/configsnap.spec index 924ac3c..7ac7134 100644 --- a/configsnap.spec +++ b/configsnap.spec @@ -1,12 +1,11 @@ Name: configsnap -Version: 0.17.1 +Version: 0.18.0 Release: 1%{?dist} Summary: Record and compare system state License: ASL 2.0 URL: https://github.com/rackerlabs/%{name} Source0: https://github.com/rackerlabs/%{name}/archive/%{version}.tar.gz # Changes the python shebang to python2 -Patch0: python_executable.patch BuildArch: noarch BuildRequires: python2-devel BuildRequires: help2man @@ -17,7 +16,6 @@ with a previous state and identify changes %prep %setup -q -%patch0 -p0 %build help2man --include=%{name}.help2man --no-info ./%{name} -o %{name}.man @@ -42,6 +40,9 @@ install -p -m 0600 additional.conf %{buildroot}%{_sysconfdir}/%{name}/additional %{_sysconfdir}/%{name} %changelog +* Mon Feb 03 2020 Nick Rhodes - 0.18.0-1 +- Improvements to get_diff (PR 110) + * Wed Jul 03 2019 Nick Rhodes - 0.17.1-1 - Convert relative basedir to absolute path (PR 103)