summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbill-auger <mr.j.spam.me@gmail.com>2020-05-16 07:19:53 -0400
committerbill-auger <mr.j.spam.me@gmail.com>2021-01-05 22:24:56 -0500
commitc8fad9f922e846fb0ef2426f9c835f7e01ab13f3 (patch)
tree16f13dcbb31e2dbaf6a9e1f7b104851fc002b29e
parent9bc2734d439e2fe6dcd807fac46a5622c77275f8 (diff)
[duplicate-or-unpublished-pkgs]: initial script
-rwxr-xr-xsrc/maintenance-tools/duplicate-or-unpublished-pkgs125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/maintenance-tools/duplicate-or-unpublished-pkgs b/src/maintenance-tools/duplicate-or-unpublished-pkgs
new file mode 100755
index 0000000..c258feb
--- /dev/null
+++ b/src/maintenance-tools/duplicate-or-unpublished-pkgs
@@ -0,0 +1,125 @@
+#!/usr/bin/env ruby
+
+DEBUG = false
+VERBOSE = false
+ABS_PATH = '/packages/abslibre'
+CFG = '--config=/etc/pacman-all.conf'
+
+REPO_NAME = (ARGV[0] || '')
+PKG_NAME = (ARGV[1] || '')
+REPO_PATH = (Dir.exist? ABS_PATH) ? "#{ABS_PATH}/#{REPO_NAME}" : ''
+PKG_PATH = (Dir.exist? ABS_PATH) ? "#{ABS_PATH}/#{REPO_NAME}/#{PKG_NAME}" : ''
+REPO_DIR = (! REPO_NAME.empty? && (Dir.exist? REPO_PATH)) ? (Dir.new REPO_PATH) : nil
+PKG_DIR = (! PKG_NAME .empty? && (Dir.exist? PKG_PATH )) ? (Dir.new PKG_PATH ) : nil
+
+UNPUBLISHED_STATE = '(unpublished)'
+COMMITTED_STATE = '(committed )'
+PUBLISHED_STATE = '(published )->'
+UNCOMMITTED_STATE = '(uncommitted)'
+DUPLICATE_STATE = '(duplicate )->'
+TERMINAL_W = `tput cols 2> /dev/null || echo 80`.to_i
+PKG_SEPARATOR = ''.ljust TERMINAL_W , '-'
+STATE_COL_W = PUBLISHED_STATE.length
+PKG_COL_W = ((TERMINAL_W - STATE_COL_W) / 2) - 2
+
+@results = {}
+@local_pkg = ''
+
+
+(puts "abs dir does not exist" ; exit 1) if REPO_PATH.empty?
+(puts "no repo dir specified" ; exit 1) if REPO_NAME.empty?
+(puts "no such repo dir: '#{REPO_NAME}'" ; exit 1) if REPO_DIR .nil?
+(puts "no such package dir: '#{PKG_NAME}'" ; exit 1) if ! PKG_NAME .empty? &&
+ PKG_DIR .nil?
+
+
+def DEBUG_RAW_DATA repo_pkgs_data ; DEBUG && (print "repo_pkgs_data[#{repo_pkgs_data.class}|#{repo_pkgs_data.size}|]\n" ; pp repo_pkgs_data) ; end ;
+def DEBUG_PKG_DATA all_repo_pkgs ; DEBUG && (print "all_repo_pkgs[#{all_repo_pkgs.class}|#{all_repo_pkgs.size}|]\n" ; pp all_repo_pkgs) ; end ;
+def DEBUG_STATE_DATA this_repo_pkg , dup_repo_pkgs ; DEBUG && (print "this_repo_pkg=#{this_repo_pkg}\n" ; print "dup_repo_pkgs=#{dup_repo_pkgs}\n") ; end ;
+
+
+def collect_duplicate_pkgs pkg_name
+ local_pkg = "#{REPO_NAME}/#{pkg_name}"
+ repo_pkgs_data = pacman_pkg_data pkg_name
+ all_repo_pkgs = []
+
+DEBUG_RAW_DATA repo_pkgs_data
+
+ until repo_pkgs_data.empty? do
+ all_repo_pkgs << (repo_pkgs_data.shift.split ':')[1].strip + '/' +
+ (repo_pkgs_data.shift.split ':')[1].strip + '-' +
+ (repo_pkgs_data.shift.split ':')[1].strip
+ end
+
+ if ! all_repo_pkgs.empty?
+
+DEBUG_PKG_DATA all_repo_pkgs
+
+ dup_repo_pkgs = all_repo_pkgs.reject { | repo_pkg | repo_pkg.start_with? "#{REPO_NAME}/" }
+ this_repo_pkg = (all_repo_pkgs - dup_repo_pkgs).first
+
+DEBUG_STATE_DATA this_repo_pkg , dup_repo_pkgs
+
+ if this_repo_pkg.nil?
+ add_result UNPUBLISHED_STATE , local_pkg
+ add_result COMMITTED_STATE , local_pkg if under_vcs? local_pkg
+ else
+ add_result PUBLISHED_STATE , local_pkg , this_repo_pkg
+ add_result UNCOMMITTED_STATE , local_pkg unless under_vcs? local_pkg
+ end
+ dup_repo_pkgs.each { | dup_pkg | add_result DUPLICATE_STATE , local_pkg , dup_pkg }
+ else
+ add_result UNPUBLISHED_STATE , local_pkg
+ add_result COMMITTED_STATE , local_pkg if under_vcs? local_pkg
+ end
+end
+
+def pacman_pkg_data pkg_name
+ `LANG=C pacman #{CFG} -Si #{pkg_name} 2> /dev/null | egrep 'Repository|Name|Version'`.lines :chomp => true
+end
+
+def under_vcs? local_pkg
+ system "git -C #{ABS_PATH} ls-files --error-unmatch #{local_pkg}/PKGBUILD &> /dev/null"
+end
+
+def add_result state , local_pkg , repo_pkg=''
+ ((@results[local_pkg] ||= {})[state] ||= []) << repo_pkg
+end
+
+def fit_to_width text , width ; (text.ljust width).slice 0 , width ; end ;
+
+
+## main entry ##
+
+print "update package database \n"
+`sudo pacman #{CFG} -Sy 2> /dev/null`
+print "gathering package data for: #{"#{REPO_NAME}/#{PKG_NAME}".gsub /\/$/ , ''}\n"
+
+if PKG_NAME.empty?
+ REPO_DIR.each_child { | pkg_name | collect_duplicate_pkgs pkg_name }
+else
+ collect_duplicate_pkgs PKG_NAME
+end
+
+n_inconsistencies = 0
+@results.keys.sort { | a , b | a <=> b }.each do | local_pkg |
+ pkg_data = @results[local_pkg]
+
+ next unless VERBOSE || pkg_data.size != 1 || pkg_data[PUBLISHED_STATE].nil?
+
+ puts PKG_SEPARATOR ; n_inconsistencies = n_inconsistencies + 1 ;
+
+ [ UNPUBLISHED_STATE , COMMITTED_STATE ,
+ PUBLISHED_STATE , UNCOMMITTED_STATE ,
+ DUPLICATE_STATE ].each do | state |
+ next unless repo_pkgs = pkg_data[state]
+
+ repo_pkgs.each do | repo_pkg |
+ puts [ (fit_to_width local_pkg , PKG_COL_W ) ,
+ (fit_to_width state , STATE_COL_W) ,
+ (fit_to_width repo_pkg , PKG_COL_W ) ].join ' '
+ local_pkg = ''
+ end
+ end
+end
+puts "#{PKG_SEPARATOR}\n#{n_inconsistencies} inconsistencies detected"