[Commits] [SCM] themes branch, master, updated. 20140629-40-g613f8ba

mones at claws-mail.org mones at claws-mail.org
Wed Sep 28 18:35:30 CEST 2022


The branch, master has been updated
       via  613f8ba67e981419d0057053560c8ce281e8535d (commit)
      from  f9c97e277802b924b577071d49501ff2fc231630 (commit)

Summary of changes:
 .gitignore |  13 ++++
 autogen.sh |   6 +-
 generate   | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 .gitignore
 create mode 100755 generate


- Log -----------------------------------------------------------------
commit 613f8ba67e981419d0057053560c8ce281e8535d
Author: Ricardo Mones <ricardo at mones.org>
Date:   Wed Sep 28 18:34:39 2022 +0200

    Generate build automagically

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..81c459a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+Makefile
+Makefile.am
+Makefile.in
+aclocal.m4
+autom4te.cache/*
+claws-mail-themes-*.tar.*
+config.log
+config.status
+configure
+configure~
+configure.ac
+install-sh
+missing
diff --git a/autogen.sh b/autogen.sh
index 622b9d9..56c4225 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,3 +1,7 @@
 #!/bin/sh
 
-aclocal   && automake --add-missing --foreign --copy   && autoconf   && ./configure --enable-maintainer-mode 
+./generate --replace --quiet \
+    && aclocal \
+    && automake --add-missing --foreign --copy \
+    && autoconf \
+    && ./configure --enable-maintainer-mode
diff --git a/generate b/generate
new file mode 100755
index 0000000..b44fbaf
--- /dev/null
+++ b/generate
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+
+# Copyright © 2022 Ricardo Mones <ricardo at mones.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import os
+import glob
+import logging
+import argparse
+import subprocess
+
+PATH_PREFIX = {'svg-themes/': 'svg_'}
+SUPPORTED_ICONS = ['xpm', 'png', 'svg']
+
+def get_git_version():
+    try:
+        described = subprocess.check_output(
+            ['git', 'describe', '--always', '--abbrev=6'])
+        version = described.decode('utf-8').rstrip().replace('-', '.')
+        logging.debug('got git version "{}"'.format(version))
+        return version
+    except Exception as ex:
+        raise RuntimeError('error running git: {}'.format(str(ex)))
+
+def config_log(verbose, debug):
+    if debug:
+        log_level = logging.DEBUG
+    else:
+        log_level = logging.INFO if verbose else logging.WARNING
+    logging.basicConfig(
+        format='%(levelname)s %(message)s',
+        level=log_level)
+
+def is_candidate(entry):
+    return entry.is_dir() \
+        and not entry.path.endswith('.git')
+
+def is_theme(dir_name):
+    return os.path.exists('{}/.claws_themeinfo'.format(dir_name))
+
+def check_replace(filename, replace, unlink=False):
+    if os.path.exists(filename):
+        if replace:
+            logging.info('replacing file {}'.format(filename))
+            if unlink:
+                os.unlink(filename)
+        else:
+            raise RuntimeError('file "{}" already exists'.format(filename))
+
+
+class Theme:
+
+    def __init__(self, dir_name):
+        # sanity check
+        if not os.path.isdir(dir_name):
+            raise RuntimeError('missing directory "{}"'.format(dir_name))
+        # keep directory
+        name = dir_name.rstrip(os.sep) if dir_name.endswith(os.sep) else dir_name
+        self.dir_name = name
+        # get theme type and count
+        self.theme_type, self.theme_count = self.get_theme_type()
+
+    def get_dest_dir(self):
+        dd = self.dir_name
+        for path in PATH_PREFIX.keys():
+            if path in dd:
+                dd = dd.replace(path, PATH_PREFIX[path])
+        logging.debug('installation dir is "{}"'.format(dd))
+        return dd
+
+    def get_theme_type(self):
+        dn = self.dir_name
+        logging.debug('checking theme type on "{}"'.format(dn))
+        current = (None, 0)
+        for image_type in SUPPORTED_ICONS:
+            n = len(glob.glob('{}/*.{}'.format(dn, image_type)))
+            logging.debug('found {} {} icons'.format(n, image_type))
+            if n > current[1]:
+                current = (image_type, n)
+        logging.debug('theme type for "{}" is {} with {} icons'.format(dn, *current))
+        return current
+
+    def get_data_and_extra(self):
+        dn = self.dir_name
+        ext = self.theme_type
+        data = [item
+            for item in glob.glob('{}/*.{}'.format(dn, ext))]
+        extra = [os.path.split(item)[1]
+            for item in glob.glob('{}/*'.format(dn)) if item not in data]
+        data = [os.path.split(item)[1]
+            for item in data]
+        logging.debug('found {} icons and {} other files'.format(len(data), len(extra)))
+        return (data, extra)
+
+    def add_build(self, replace):
+        dn = self.dir_name
+        # check Makefile.am
+        makefile = '{}/Makefile.am'.format(dn)
+        check_replace(makefile, replace, True)
+        # get file lists
+        data, extra = self.get_data_and_extra()
+        # create Makefile.am
+        dest_dir = self.get_dest_dir()
+        with open(makefile, 'w', encoding='utf-8') as mkf:
+            mkf.write('themedir = $(prefix)/share/claws-mail/themes/{}\n'.format(dest_dir))
+            mkf.write('\n')
+            mkf.write('dist_theme_DATA = .claws_themeinfo \\\n ')
+            mkf.write(' \\\n '.join(sorted(data)))
+            mkf.write('\n\n')
+            if len(extra) > 0:
+                mkf.write('EXTRA_DIST = ')
+                mkf.write(' \\\n '.join(sorted(extra)))
+                mkf.write('\n\n')
+        logging.info('{} created'.format(makefile))
+
+
+class Generator:
+
+    def __init__(self, replace):
+        if not os.path.isfile('./claws-mail-themes'):
+            raise RuntimeError('must be run at toplevel directory')
+        if not os.path.isdir('./.git'):
+            raise RuntimeError('must be run within a git working directory')
+        self.theme_dirs = sorted([t[2:] for t in self.scan_tree('./') if is_theme(t)])
+        self.replace = replace
+        self.themes = []
+
+    def scan_tree(self, dirname):
+        themes = [f.path for f in os.scandir(dirname) if is_candidate(f)]
+        for dirname in list(themes):
+            themes.extend(self.scan_tree(dirname))
+        return themes
+
+    def add_configure(self, version):
+        configure = './configure.ac'
+        logging.info('generating {}'.format(configure))
+        check_replace(configure, self.replace)
+        header = '\n'.join(['AC_PREREQ(2.59d)',
+            'AC_INIT([claws-mail-themes], [{}])'.format(version),
+            'AC_CONFIG_SRCDIR([achileus-noname/address.xpm])',
+            'AM_INIT_AUTOMAKE', '',
+            'AM_MAINTAINER_MODE', '',
+            'dnl Checks for programs.',
+            'AC_PROG_INSTALL', '',
+            'AC_OUTPUT([',
+            'Makefile\n'])
+        added = []
+        with open(configure, 'w', encoding='utf-8') as caf:
+            caf.write(header)
+            for t in self.theme_dirs:
+                theme = Theme(t)
+                caf.write('{}/Makefile\n'.format(t))
+                theme.add_build(self.replace)
+                added.append(t)
+                self.themes.append(theme)
+            caf.write('])\n')
+        logging.debug('configured {} themes'.format(len(added)))
+        return added
+
+    def print_stats(self):
+        if self.themes:
+            by_type = { it: 0 for it in SUPPORTED_ICONS }
+            by_lowest_c = { it: (999, '') for it in SUPPORTED_ICONS }
+            by_highest_c = { it: (0, '') for it in SUPPORTED_ICONS }
+            for t in self.themes:
+                for it in SUPPORTED_ICONS:
+                    if t.theme_type == it:
+                        by_type[it] += 1
+                        if t.theme_count < by_lowest_c[it][0]:
+                            by_lowest_c[it] = (t.theme_count, t.dir_name)
+                        if t.theme_count > by_highest_c[it][0]:
+                            by_highest_c[it] = (t.theme_count, t.dir_name)
+            n = len(SUPPORTED_ICONS) - 1
+            t = len(self.themes)
+            print('%d themes configured:' % t)
+            for i, it in enumerate(sorted(SUPPORTED_ICONS)):
+                j, k = ('├', '│') if i < n else ('└', ' ')
+                print('%s %d with %s icons (%.2f %%):'
+                    % (j, by_type[it], it, (by_type[it]/t * 100.0)))
+                print('%s  ├ “%s” has the highest icon count (%d)'
+                    % (k, by_highest_c[it][1], by_highest_c[it][0]))
+                print('%s  └ “%s” has the lowest (%d)'
+                    % (k, by_lowest_c[it][1], by_lowest_c[it][0]))
+
+    def generate(self, quiet):
+        makefile = './Makefile.am'
+        check_replace(makefile, self.replace)
+        configured = self.add_configure(get_git_version())
+        logging.info('generating {}'.format(makefile))
+        with open(makefile, 'w', encoding='utf-8') as mkf:
+            mkf.write('EXTRA_DIST = claws-mail-themes\n\n')
+            mkf.write('AUTOMAKE_OPTIONS = dist-bzip2 dist-xz\n\n')
+            mkf.write('SUBDIRS = ')
+            mkf.write(' \\\n '.join(configured)) # already sorted
+        if not quiet:
+            self.print_stats()
+
+
+def main():
+    par = argparse.ArgumentParser(
+        description='Generate build files for themes')
+    par.add_argument('-d', '--debug', action='store_true',
+        help='enable debug log messages (implies --verbose)')
+    par.add_argument('-q', '--quiet', action='store_true',
+        help='do not print summary')
+    par.add_argument('-r', '--replace', action='store_true',
+        help='overwrite existing files')
+    par.add_argument('-v', '--verbose', action='store_true',
+        help='enable informative log messages')
+    arg = par.parse_args()
+    config_log(arg.verbose, arg.debug)
+    gen = Generator(arg.replace)
+    logging.info('generation started')
+    gen.generate(arg.quiet)
+    logging.info('generation finished')
+
+if __name__ == '__main__':
+    try:
+        main()
+    except Exception as ex:
+        logging.error(str(ex))

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail Themes


More information about the Commits mailing list