openSUSE Commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
April 2018
- 1 participants
- 1679 discussions
Hello community,
here is the log from the commit of package openSUSE-release-tools for openSUSE:Factory checked in at 2018-04-27 16:09:21
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openSUSE-release-tools (Old)
and /work/SRC/openSUSE:Factory/.openSUSE-release-tools.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openSUSE-release-tools"
Fri Apr 27 16:09:21 2018 rev:87 rq:601643 version:20180426.2282f15
Changes:
--------
--- /work/SRC/openSUSE:Factory/openSUSE-release-tools/openSUSE-release-tools.changes 2018-04-26 13:38:38.626733390 +0200
+++ /work/SRC/openSUSE:Factory/.openSUSE-release-tools.new/openSUSE-release-tools.changes 2018-04-27 16:09:26.550026327 +0200
@@ -1,0 +2,42 @@
+Thu Apr 26 16:01:14 UTC 2018 - opensuse-releaseteam(a)opensuse.org
+
+- Update to version 20180426.2282f15:
+ * metrics/grafana/dashboard: remove y-axis max from "Weekly Revisions".
+
+-------------------------------------------------------------------
+Thu Apr 26 11:19:15 UTC 2018 - opensuse-releaseteam(a)opensuse.org
+
+- Update to version 20180426.2aba87c:
+ * freeze_command: rebase staging project do not erase users data
+
+-------------------------------------------------------------------
+Thu Apr 26 03:06:20 UTC 2018 - opensuse-releaseteam(a)opensuse.org
+
+- Update to version 20180425.abd03b3:
+ * metrics: ingest_dashboard_config: rename seen to previous.
+ * metrics: ingest_dashboard_config: initialize seen with last record keys.
+ * metrics: ingest_dashboard_config: only fill missing values once.
+
+-------------------------------------------------------------------
+Thu Apr 26 02:58:28 UTC 2018 - opensuse-releaseteam(a)opensuse.org
+
+- Update to version 20180425.94fefaf:
+ * metrics/grafana/dashboard: add release schedule annotation.
+ * metrics/grafana/dashboard: include dashboard description.
+ * metrics/grafana/dashboard: change all selectors to last.
+
+-------------------------------------------------------------------
+Thu Apr 26 02:46:51 UTC 2018 - opensuse-releaseteam(a)opensuse.org
+
+- Update to version 20180425.ade9313:
+ * metrics: dashboard: drop dashboard measurement in favor of dashboard_revision.
+ * metrics: dashboard: include revisions graph.
+
+-------------------------------------------------------------------
+Thu Apr 26 02:11:24 UTC 2018 - opensuse-releaseteam(a)opensuse.org
+
+- Update to version 20180425.adab26c:
+ * repo_checker: provide whitelist_clean subcommand.
+ * osclib/core: correct BINARY_REGEX by making it greedy.
+
+-------------------------------------------------------------------
Old:
----
openSUSE-release-tools-20180425.8bb627d.obscpio
New:
----
openSUSE-release-tools-20180426.2282f15.obscpio
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ openSUSE-release-tools.spec ++++++
--- /var/tmp/diff_new_pack.j0WO9C/_old 2018-04-27 16:09:28.521954004 +0200
+++ /var/tmp/diff_new_pack.j0WO9C/_new 2018-04-27 16:09:28.525953857 +0200
@@ -20,7 +20,7 @@
%define source_dir openSUSE-release-tools
%define announcer_filename factory-package-news
Name: openSUSE-release-tools
-Version: 20180425.8bb627d
+Version: 20180426.2282f15
Release: 0
Summary: Tools to aid in staging and release work for openSUSE/SUSE
License: GPL-2.0-or-later AND MIT
++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.j0WO9C/_old 2018-04-27 16:09:28.577951951 +0200
+++ /var/tmp/diff_new_pack.j0WO9C/_new 2018-04-27 16:09:28.577951951 +0200
@@ -1,6 +1,6 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://github.com/openSUSE/openSUSE-release-tools.git</param>
- <param name="changesrevision">8bb627d9bfe07dc22af6910b73564eef7cb0f53d</param>
+ <param name="changesrevision">2282f15cf32167d4eddadce3a87205e44e5e0a59</param>
</service>
</servicedata>
++++++ openSUSE-release-tools-20180425.8bb627d.obscpio -> openSUSE-release-tools-20180426.2282f15.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openSUSE-release-tools-20180425.8bb627d/metrics/grafana/dashboard.json new/openSUSE-release-tools-20180426.2282f15/metrics/grafana/dashboard.json
--- old/openSUSE-release-tools-20180425.8bb627d/metrics/grafana/dashboard.json 2018-04-25 11:44:55.000000000 +0200
+++ new/openSUSE-release-tools-20180426.2282f15/metrics/grafana/dashboard.json 2018-04-26 17:55:07.000000000 +0200
@@ -24,9 +24,19 @@
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
+ },
+ {
+ "datasource": "$project",
+ "enable": false,
+ "hide": false,
+ "iconColor": "rgba(255, 96, 96, 1)",
+ "name": "Release Schedule",
+ "query": "select description from release_schedule where $timeFilter",
+ "showIn": 0
}
]
},
+ "description": "Metrics pertaining to data extracted from the dashboard container.",
"editable": true,
"gnetId": null,
"graphTooltip": 0,
@@ -103,7 +113,7 @@
},
{
"params": [],
- "type": "max"
+ "type": "last"
},
{
"params": [
@@ -221,7 +231,7 @@
},
{
"params": [],
- "type": "mean"
+ "type": "last"
},
{
"params": [
@@ -239,7 +249,7 @@
},
{
"params": [],
- "type": "mean"
+ "type": "last"
},
{
"params": [
@@ -257,7 +267,7 @@
},
{
"params": [],
- "type": "mean"
+ "type": "last"
},
{
"params": [
@@ -375,7 +385,7 @@
},
{
"params": [],
- "type": "max"
+ "type": "last"
},
{
"params": [
@@ -393,7 +403,7 @@
},
{
"params": [],
- "type": "max"
+ "type": "last"
},
{
"params": [
@@ -411,7 +421,7 @@
},
{
"params": [],
- "type": "max"
+ "type": "last"
},
{
"params": [
@@ -562,6 +572,118 @@
"min": null,
"show": true
},
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ }
+ ]
+ },
+ {
+ "aliasColors": {},
+ "bars": true,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "$project",
+ "description": "The number of revisions to dashboard container made during a week.",
+ "fill": 1,
+ "gridPos": {
+ "h": 9,
+ "w": 24,
+ "x": 0,
+ "y": 36
+ },
+ "id": 7,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": false,
+ "total": false,
+ "values": false
+ },
+ "lines": false,
+ "linewidth": 1,
+ "links": [],
+ "nullPointMode": "null",
+ "percentage": false,
+ "pointradius": 5,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "alias": "$col",
+ "groupBy": [
+ {
+ "params": [
+ "1w"
+ ],
+ "type": "time"
+ }
+ ],
+ "measurement": "dashboard_revision",
+ "orderByTime": "ASC",
+ "policy": "default",
+ "refId": "A",
+ "resultFormat": "time_series",
+ "select": [
+ [
+ {
+ "params": [
+ "revision"
+ ],
+ "type": "field"
+ },
+ {
+ "params": [],
+ "type": "count"
+ },
+ {
+ "params": [
+ "count"
+ ],
+ "type": "alias"
+ }
+ ]
+ ],
+ "tags": []
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeShift": null,
+ "title": "Weekly Revisions",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "decimals": null,
+ "format": "short",
+ "label": "",
+ "logBase": 1,
+ "max": null,
+ "min": null,
+ "show": true
+ },
{
"format": "short",
"label": null,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openSUSE-release-tools-20180425.8bb627d/metrics.py new/openSUSE-release-tools-20180426.2282f15/metrics.py
--- old/openSUSE-release-tools-20180425.8bb627d/metrics.py 2018-04-25 11:44:55.000000000 +0200
+++ new/openSUSE-release-tools-20180426.2282f15/metrics.py 2018-04-26 17:55:07.000000000 +0200
@@ -410,21 +410,32 @@
return None
def ingest_dashboard_config(content):
- if not hasattr(ingest_dashboard_config, 'seen'):
- ingest_dashboard_config.seen = set()
+ if not hasattr(ingest_dashboard_config, 'previous'):
+ result = client.query('SELECT * FROM dashboard_config ORDER BY time DESC LIMIT 1')
+ if result:
+ # Extract last point and remove zero values since no need to fill.
+ point = next(result.get_points())
+ point = {k: v for (k, v) in point.iteritems() if k != 'time' and v != 0}
+ ingest_dashboard_config.previous = set(point.keys())
+ else:
+ ingest_dashboard_config.previous = set()
fields = {}
for key, value in content.items():
if key.startswith('repo_checker-binary-whitelist'):
- ingest_dashboard_config.seen.add(key)
+ ingest_dashboard_config.previous.add(key)
fields[key] = len(value.split())
# Ensure any previously seen key are filled with zeros if no longer present
# to allow graphs to fill with previous.
- missing = ingest_dashboard_config.seen - set(fields.keys())
- for key in missing:
- fields[key] = 0
+ fields_keys = set(fields.keys())
+ missing = ingest_dashboard_config.previous - fields_keys
+ if len(missing):
+ ingest_dashboard_config.previous = fields_keys
+
+ for key in missing:
+ fields[key] = 0
return fields
@@ -446,22 +457,12 @@
}
def ingest_dashboard_revision_get():
- result = client.query('SELECT revision FROM dashboard ORDER BY time DESC LIMIT 1')
+ result = client.query('SELECT revision FROM dashboard_revision ORDER BY time DESC LIMIT 1')
if result:
return next(result.get_points())['revision']
return None
-def ingest_dashboard_revision_put(revision):
- client.drop_measurement('dashboard')
- client.write_points([{
- 'measurement': 'dashboard',
- 'fields': {
- 'revision': revision,
- },
- 'time': timestamp(datetime.now()),
- }], 's')
-
def ingest_dashboard(api):
index = revision_index(api)
@@ -497,6 +498,14 @@
'time': time,
})
+ points.append({
+ 'measurement': 'dashboard_revision',
+ 'fields': {
+ 'revision': revision,
+ },
+ 'time': time,
+ })
+
if len(points) >= 1000:
client.write_points(points, 's')
count += len(points)
@@ -506,9 +515,7 @@
client.write_points(points, 's')
count += len(points)
- # Keep track of last revision process to start after that next time.
- print('storing last revision processed: {}'.format(revision))
- ingest_dashboard_revision_put(revision)
+ print('last revision processed: {}'.format(revision))
return count
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openSUSE-release-tools-20180425.8bb627d/osclib/core.py new/openSUSE-release-tools-20180426.2282f15/osclib/core.py
--- old/openSUSE-release-tools-20180425.8bb627d/osclib/core.py 2018-04-25 11:44:55.000000000 +0200
+++ new/openSUSE-release-tools-20180426.2282f15/osclib/core.py 2018-04-26 17:55:07.000000000 +0200
@@ -16,7 +16,7 @@
from osc.core import show_project_meta
from osclib.memoize import memoize
-BINARY_REGEX = r'(?:.*::)?(?P<filename>(?P<name>.*?)-(?P<version>[^-]+)-(?P<release>[^-]+)\.(?P<arch>[^-\.]+))'
+BINARY_REGEX = r'(?:.*::)?(?P<filename>(?P<name>.*)-(?P<version>[^-]+)-(?P<release>[^-]+)\.(?P<arch>[^-\.]+))'
RPM_REGEX = BINARY_REGEX + '\.rpm'
BinaryParsed = namedtuple('BinaryParsed', ('package', 'filename', 'name', 'arch'))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openSUSE-release-tools-20180425.8bb627d/osclib/freeze_command.py new/openSUSE-release-tools-20180426.2282f15/osclib/freeze_command.py
--- old/openSUSE-release-tools-20180425.8bb627d/osclib/freeze_command.py 2018-04-25 11:44:55.000000000 +0200
+++ new/openSUSE-release-tools-20180426.2282f15/osclib/freeze_command.py 2018-04-26 17:55:07.000000000 +0200
@@ -43,6 +43,9 @@
meta = ET.fromstring(self.prj_meta_for_bootstrap_copy(self.prj))
meta.find('title').text = oldmeta.find('title').text
meta.find('description').text = oldmeta.find('description').text
+ for person in oldmeta.findall('person'):
+ # the xml has a fixed structure
+ meta.insert(2, ET.Element('person', role=person.get('role'), userid=person.get('userid')))
self.api.retried_PUT(url, ET.tostring(meta))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/openSUSE-release-tools-20180425.8bb627d/repo_checker.py new/openSUSE-release-tools-20180426.2282f15/repo_checker.py
--- old/openSUSE-release-tools-20180425.8bb627d/repo_checker.py 2018-04-25 11:44:55.000000000 +0200
+++ new/openSUSE-release-tools-20180426.2282f15/repo_checker.py 2018-04-26 17:55:07.000000000 +0200
@@ -1,5 +1,7 @@
#!/usr/bin/python
+from __future__ import print_function
+
import cmdln
from collections import namedtuple
import hashlib
@@ -518,6 +520,77 @@
self.review_messages['accepted'] = 'delete request is safe'
return True
+ def whitelist_clean(self, project):
+ from copy import copy
+ from difflib import unified_diff
+ from osclib.core import BINARY_REGEX
+
+ api = self.staging_api(project)
+
+ # Determine which binaries are mentioned in repo_checker output.
+ content = api.dashboard_content_load('repo_checker')
+ sections = self.install_check_parse(content)
+ binaries = set()
+ for section in sections:
+ for binary in section.binaries:
+ match = re.match(BINARY_REGEX, binary)
+ if match:
+ binaries.add(match.group('name'))
+
+ # Find whitelist config entries and filter list to only those mentioned.
+ prefix = 'repo_checker-binary-whitelist'
+ binaries_common = None
+ whitelists = {}
+ whitelists_remaining = {}
+ for key, value in self.staging_config[project].items():
+ if not key.startswith(prefix):
+ continue
+
+ whitelists[key] = set(value.split())
+ whitelists_remaining[key] = whitelists[key].intersection(binaries)
+
+ if key != prefix:
+ if binaries_common is None:
+ binaries_common = whitelists_remaining[key]
+ else:
+ binaries_common = binaries_common.intersection(whitelists_remaining[key])
+
+ if len(binaries_common):
+ # Remove entries common to all archs and place in common whitelist.
+ whitelists_remaining[prefix].update(binaries_common)
+
+ for key, value in whitelists_remaining.items():
+ if key == prefix:
+ continue
+
+ whitelists_remaining[key] = whitelists_remaining[key] - binaries_common
+
+ # Update whitelist entries with new values.
+ config = api.dashboard_content_load('config').splitlines(True)
+ config_new = copy(config)
+ for key, value in whitelists_remaining.items():
+ if value != whitelists[key]:
+ self.whitelist_clean_set(config_new, key, ' '.join(value))
+
+ if config == config_new:
+ print('No changes')
+ return
+
+ # Present diff and prompt to apply.
+ print(''.join(unified_diff(config, config_new, fromfile='config.orig', tofile='config.new')))
+ print('Apply config changes? [y/n] (y): ', end='')
+ response = raw_input().lower()
+ if response == '' or response == 'y':
+ api.dashboard_content_save('config', ''.join(config_new), 'repo_checker whitelist clean')
+
+ def whitelist_clean_set(self, config, key, value):
+ # Unfortunately even OscConfigParser does not preserve empty lines.
+ for i, line in enumerate(config):
+ if line.startswith(key + ' ='):
+ config[i] = '{} = {}\n'.format(key, value) if value else '{} =\n'.format(key)
+
+ return config
+
class CommandLineInterface(ReviewBot.CommandLineInterface):
@@ -550,6 +623,10 @@
self.checker.check_requests() # Needed to properly init ReviewBot.
self.checker.project_only(project, opts.post_comments)
+ def do_whitelist_clean(self, subcmd, opts, project):
+ self.checker.check_requests() # Needed to properly init ReviewBot.
+ self.checker.whitelist_clean(project)
+
if __name__ == "__main__":
app = CommandLineInterface()
sys.exit(app.main())
++++++ openSUSE-release-tools.obsinfo ++++++
--- /var/tmp/diff_new_pack.j0WO9C/_old 2018-04-27 16:09:29.281926132 +0200
+++ /var/tmp/diff_new_pack.j0WO9C/_new 2018-04-27 16:09:29.281926132 +0200
@@ -1,5 +1,5 @@
name: openSUSE-release-tools
-version: 20180425.8bb627d
-mtime: 1524649495
-commit: 8bb627d9bfe07dc22af6910b73564eef7cb0f53d
+version: 20180426.2282f15
+mtime: 1524758107
+commit: 2282f15cf32167d4eddadce3a87205e44e5e0a59
1
0
Hello community,
here is the log from the commit of package rmt-server for openSUSE:Factory checked in at 2018-04-27 16:09:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rmt-server (Old)
and /work/SRC/openSUSE:Factory/.rmt-server.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rmt-server"
Fri Apr 27 16:09:18 2018 rev:8 rq:601636 version:0.0.7
Changes:
--------
--- /work/SRC/openSUSE:Factory/rmt-server/rmt-server.changes 2018-04-11 14:02:16.474188989 +0200
+++ /work/SRC/openSUSE:Factory/.rmt-server.new/rmt-server.changes 2018-04-27 16:09:18.962304615 +0200
@@ -1,0 +2,30 @@
+Thu Apr 26 14:58:45 UTC 2018 - tmuntaner(a)suse.com
+
+- Added supportconfig plugin
+ See: https://github.com/SUSE/rmt/pull/146
+- Rename organizations_products.json to organizations_products_unscoped.json (fixes bsc#1088687)
+ See: https://github.com/SUSE/rmt/pull/151
+- Improved log formatting in journald
+ See: https://github.com/SUSE/rmt/pull/145
+
+-------------------------------------------------------------------
+Wed Apr 25 14:47:18 UTC 2018 - tmuntaner(a)suse.com
+
+- version 0.0.7
+- Fixed offline repository sync with usb (bsc#1089038)
+ See: https://github.com/SUSE/rmt/pull/147
+- Removed unique index for uuid in HwInfo table
+ See: https://github.com/SUSE/rmt/pull/142
+- "rmt-cli products enable ..." enables recommended extensions in SLE 15
+ See: https://github.com/SUSE/rmt/pull/141
+- Added RMT header in requests for Connect API
+ See: https://github.com/SUSE/rmt/pull/139
+
+-------------------------------------------------------------------
+Thu Apr 19 15:09:41 UTC 2018 - skotov(a)suse.com
+
+- version 0.0.6
+- storing hardware info
+ https://github.com/SUSE/rmt/pull/138
+
+-------------------------------------------------------------------
Old:
----
rmt-server-0.0.5.tar.bz2
New:
----
rmt-server-0.0.7.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ rmt-server.spec ++++++
--- /var/tmp/diff_new_pack.NkqGpe/_old 2018-04-27 16:09:20.502248135 +0200
+++ /var/tmp/diff_new_pack.NkqGpe/_new 2018-04-27 16:09:20.502248135 +0200
@@ -27,7 +27,7 @@
%define rmt_group nginx
Name: rmt-server
-Version: 0.0.5
+Version: 0.0.7
Release: 0
Summary: Repository mirroring tool and registration proxy for SCC
License: GPL-2.0-or-later
@@ -150,6 +150,10 @@
-e 's/^BUNDLE_JOBS: .*/BUNDLE_JOBS: "1"/' \
%{buildroot}%{app_dir}/.bundle/config
+# supportconfig plugin
+mkdir -p %{buildroot}%{_libexecdir}/supportconfig/plugins
+install -D -m 544 support/rmt %{buildroot}%{_libexecdir}/supportconfig/plugins/rmt
+
# cleanup of /usr/bin/env commands
grep -rl '\/usr\/bin\/env ruby' %{buildroot}%{lib_dir}/vendor/bundle/ruby | xargs \
sed -i -e 's@\/usr\/bin\/env ruby.ruby2\.5@\/usr\/bin\/ruby\.ruby2\.5@g' \
@@ -182,12 +186,14 @@
%defattr(-,root,root)
%attr(-,%{rmt_user},%{rmt_group}) %{app_dir}
%attr(-,%{rmt_user},%{rmt_group}) %{data_dir}
+%dir %{_libexecdir}/supportconfig
+%dir %{_libexecdir}/supportconfig/plugins
+%dir %{_sysconfdir}/nginx
+%dir %{_sysconfdir}/nginx/vhosts.d
%config(noreplace) %{_sysconfdir}/rmt.conf
%config(noreplace) %{_sysconfdir}/nginx/vhosts.d/rmt-server-http.conf
%config(noreplace) %{_sysconfdir}/nginx/vhosts.d/rmt-server-https.conf
%doc %{_mandir}/man8/rmt.8.gz
-%{_sysconfdir}/nginx
-%{_sysconfdir}/nginx/vhosts.d
%{_bindir}/rmt-cli
%{_sbindir}/rcrmt
%{_sbindir}/rcrmt-migration
@@ -202,6 +208,7 @@
%{_unitdir}/rmt-server-sync.timer
%{_libdir}/rmt
+%{_libexecdir}/supportconfig/plugins/rmt
%pre
getent group %{rmt_group} >/dev/null || %{_sbindir}/groupadd -r %{rmt_group}
++++++ rmt-migration.service ++++++
--- /var/tmp/diff_new_pack.NkqGpe/_old 2018-04-27 16:09:20.574245495 +0200
+++ /var/tmp/diff_new_pack.NkqGpe/_new 2018-04-27 16:09:20.574245495 +0200
@@ -7,6 +7,7 @@
[Service]
Type=oneshot
User=_rmt
+Environment=LOG_TO_JOURNALD=1
WorkingDirectory=/usr/share/rmt
ExecStart=/usr/share/rmt/bin/rails db:create db:migrate RAILS_ENV=production
++++++ rmt-server-0.0.5.tar.bz2 -> rmt-server-0.0.7.tar.bz2 ++++++
/work/SRC/openSUSE:Factory/rmt-server/rmt-server-0.0.5.tar.bz2 /work/SRC/openSUSE:Factory/.rmt-server.new/rmt-server-0.0.7.tar.bz2 differ: char 11, line 1
++++++ rmt-server-mirror.service ++++++
--- /var/tmp/diff_new_pack.NkqGpe/_old 2018-04-27 16:09:20.630243440 +0200
+++ /var/tmp/diff_new_pack.NkqGpe/_new 2018-04-27 16:09:20.634243294 +0200
@@ -6,6 +6,7 @@
[Service]
Type=simple
Restart=no
+Environment=LOG_TO_JOURNALD=1
ExecStart=/usr/share/rmt/bin/rmt-cli mirror
[Install]
++++++ rmt-server-sync.service ++++++
--- /var/tmp/diff_new_pack.NkqGpe/_old 2018-04-27 16:09:20.690241241 +0200
+++ /var/tmp/diff_new_pack.NkqGpe/_new 2018-04-27 16:09:20.694241094 +0200
@@ -6,6 +6,7 @@
[Service]
Type=simple
Restart=no
+Environment=LOG_TO_JOURNALD=1
ExecStart=/usr/share/rmt/bin/rmt-cli sync
[Install]
++++++ rmt.8.gz ++++++
--- /var/tmp/diff_new_pack.NkqGpe/_old 2018-04-27 16:09:20.734239627 +0200
+++ /var/tmp/diff_new_pack.NkqGpe/_new 2018-04-27 16:09:20.734239627 +0200
@@ -137,6 +137,44 @@
.SH "Configuration"
Available configuration options can be found in the \fBetc/rmt\.conf\fR file\.
.
+.P
+The recommended way to perform initial configuration is using the YaST RMT module \fIhttps://github\.com/SUSE/yast2\-rmt\fR\. The RPM package is available on OBS \fIhttps://build\.opensuse\.org/package/show/systemsmanagement:SCC:RMT/yast2\-rmt\fR\. The YaST RMT module will take care of configuring SCC credentials, setting up the database and creating SSL certificates\.
+.
+.SS "SSL certificates & HTTPS"
+By default access to API endpoints consumed by SUSEConnect is limited to HTTPS only\. nginx is configured to use SSL certificate and private key from the following locations:
+.
+.IP "\(bu" 4
+Certificate: /usr/share/rmt/ssl/rmt\-server\.crt
+.
+.IP "\(bu" 4
+Private key: /usr/share/rmt/ssl/rmt\-server\.key
+.
+.IP "" 0
+.
+.P
+YaST RMT module generates a custom certificate authority which is used to sign HTTPS certificates, which means that in order to register, this certificate authority must be trusted by the client machines\.
+.
+.IP "\(bu" 4
+When registration is performed during installation from the media or with YaST Registration module, a message will appear, prompting to trust the server certificate\.
+.
+.IP "\(bu" 4
+\fBclientSetup4RMT\.sh\fR script is provided for registering on the command line at the following URL: \fBhttp://rmt\.hostname/tools/clientSetup4RMT\.sh\fR\. The script requires only the RMT server hostname as a mandatory parameter, e\.g\.:
+.
+.IP "" 4
+.
+.nf
+
+ \./clientSetup4RMT\.sh https://rmt\.hostname/
+.
+.fi
+.
+.IP "" 0
+.
+.IP
+Executing this script will import the RMT CA\'s certificate into the trusted store and after that run SUSEConnect to register the client with the RMT\.
+.
+.IP "" 0
+.
.SS "Mirroring settings"
.
.IP "\(bu" 4
++++++ rmt.service ++++++
--- /var/tmp/diff_new_pack.NkqGpe/_old 2018-04-27 16:09:20.766238453 +0200
+++ /var/tmp/diff_new_pack.NkqGpe/_new 2018-04-27 16:09:20.766238453 +0200
@@ -9,7 +9,7 @@
Type=simple
User=_rmt
PrivateTmp=yes
-Environment=RAILS_LOG_TO_STDOUT=1
+Environment=LOG_TO_JOURNALD=1
WorkingDirectory=/usr/share/rmt
ExecStart=/usr/share/rmt/bin/rails server -e production
Restart=always
1
0
Hello community,
here is the log from the commit of package yast2-rmt for openSUSE:Factory checked in at 2018-04-27 16:09:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-rmt (Old)
and /work/SRC/openSUSE:Factory/.yast2-rmt.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yast2-rmt"
Fri Apr 27 16:09:16 2018 rev:4 rq:601631 version:0.0.4
Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-rmt/yast2-rmt.changes 2018-04-06 17:52:22.661347465 +0200
+++ /work/SRC/openSUSE:Factory/.yast2-rmt.new/yast2-rmt.changes 2018-04-27 16:09:17.846345544 +0200
@@ -1,0 +2,7 @@
+Wed Apr 18 12:06:01 UTC 2018 - ikapelyukhin(a)suse.com
+
+- version 0.0.4
+- Allow a preexisting SSL CA:
+ https://github.com/SUSE/yast2-rmt/pull/11
+
+-------------------------------------------------------------------
Old:
----
yast2-rmt-0.0.3.tar.bz2
New:
----
yast2-rmt-0.0.4.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ yast2-rmt.spec ++++++
--- /var/tmp/diff_new_pack.NHG308/_old 2018-04-27 16:09:18.474322512 +0200
+++ /var/tmp/diff_new_pack.NHG308/_new 2018-04-27 16:09:18.478322365 +0200
@@ -17,14 +17,14 @@
Name: yast2-rmt
-Version: 0.0.3
+Version: 0.0.4
Release: 0
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Source0: %{name}-%{version}.tar.bz2
-Requires: rmt-server
+Requires: rmt-server >= 0.0.5
Requires: yast2
Requires: yast2-ruby-bindings
@@ -58,6 +58,7 @@
%defattr(-,root,root)
%{yast_dir}/clients/*.rb
%{yast_dir}/lib/rmt
+%{yast_desktopdir}/rmt.desktop
%{yast_dir}/data/rmt
%doc COPYING
++++++ yast2-rmt-0.0.3.tar.bz2 -> yast2-rmt-0.0.4.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/Gemfile.lock new/yast2-rmt-0.0.4/Gemfile.lock
--- old/yast2-rmt-0.0.3/Gemfile.lock 2018-02-26 17:24:52.157255046 +0100
+++ new/yast2-rmt-0.0.4/Gemfile.lock 2018-04-18 11:54:50.758844151 +0200
@@ -9,7 +9,7 @@
ast (~> 2.4.0)
powerpack (0.1.1)
rainbow (3.0.0)
- rake (12.3.0)
+ rake (12.3.1)
rubocop (0.52.1)
parallel (~> 1.10)
parser (>= 2.4.0.2, < 3.0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/README.md new/yast2-rmt-0.0.4/README.md
--- old/yast2-rmt-0.0.3/README.md 2018-03-12 17:02:15.344583881 +0100
+++ new/yast2-rmt-0.0.4/README.md 2018-04-16 15:10:34.945032546 +0200
@@ -30,6 +30,48 @@
docker run -it yast-rmt-image rspec
```
-### Package
+### Package
-The package gets built for SLE15 here: https://build.opensuse.org/package/show/systemsmanagement:SCC:RMT/yast2-rmt
+The package gets built for SLE 15 and openSUSE Leap 15 here:
+https://build.opensuse.org/package/show/systemsmanagement:SCC:RMT/yast2-rmt
+
+You can use:
+
+```bash
+rake osc:commit
+```
+
+to commit the current version to OBS.
+
+
+#### Submit Requests to openSUSE Factory and SLES
+
+To get a maintenance request accepted, each changelog entry needs to reference a bug or feature
+request with `bsc#123` or `fate#123`.
+
+##### Factory First
+
+To submit a request to openSUSE Factory, issue this commands in the console:
+
+```bash
+osc sr systemsmanagement:SCC:RMT yast2-rmt openSUSE:Factory --no-cleanup
+```
+
+
+##### Internal Build Service
+
+To make the initial submit for a new SLES version:
+
+```bash
+osc -A https://api.suse.de sr Devel:SCC:RMT yast2-rmt SUSE:SLE-15:GA --no-cleanup
+```
+
+To submit the updated package as a maintenance update to released SLES versions:
+
+```bash
+osc -A https://api.suse.de mr Devel:SCC:RMT yast2-rmt SUSE:SLE-15:GA:Update --no-cleanup
+```
+
+You can check the status of your requests [here](https://build.opensuse.org/package/requests/systemsmanagement:SCC:RMT… and [here](https://build.suse.de/package/requests/Devel:SCC:RMT/yast2-rmt).
+
+After your requests got accepted, they still have to pass maintenance testing before they get released to customers. You can check their progress at [maintenance.suse.de](https://maintenance.suse.de/search/?q=yast2-rmt). If you still need help, the maintenance team can be reached at [maint-coord@suse.de](maint-coord@suse.de) or #maintenance on irc.suse.de.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/Rakefile new/yast2-rmt-0.0.4/Rakefile
--- old/yast2-rmt-0.0.3/Rakefile 2018-03-27 15:09:30.067122856 +0200
+++ new/yast2-rmt-0.0.4/Rakefile 2018-04-18 11:54:50.758844151 +0200
@@ -23,7 +23,7 @@
conf.obs_project = 'systemsmanagement:SCC:RMT'
# Default target for osc:build
conf.obs_target = 'openSUSE_Factory'
- conf.skip_license_check = [ %r{^Gemfile\.lock$}, %r{rmt.*\.cnf\.erb$} ]
+ conf.skip_license_check = [ %r{^Gemfile\.lock$}, %r{rmt\.desktop} , %r{rmt.*\.cnf\.erb$} ]
end
# This is required, because `yast-travis-ruby` binary calls `rake test:unit`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/package/yast2-rmt.changes new/yast2-rmt-0.0.4/package/yast2-rmt.changes
--- old/yast2-rmt-0.0.3/package/yast2-rmt.changes 2018-04-03 10:17:50.038563438 +0200
+++ new/yast2-rmt-0.0.4/package/yast2-rmt.changes 2018-04-24 11:54:43.422604842 +0200
@@ -1,4 +1,11 @@
-------------------------------------------------------------------
+Wed Apr 18 12:06:01 UTC 2018 - ikapelyukhin(a)suse.com
+
+- version 0.0.4
+- Allow a preexisting SSL CA:
+ https://github.com/SUSE/yast2-rmt/pull/11
+
+-------------------------------------------------------------------
Tue Apr 3 08:16:37 UTC 2018 - ikapelyukhin(a)suse.com
- version 0.0.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/package/yast2-rmt.spec new/yast2-rmt-0.0.4/package/yast2-rmt.spec
--- old/yast2-rmt-0.0.3/package/yast2-rmt.spec 2018-04-03 10:16:23.106209620 +0200
+++ new/yast2-rmt-0.0.4/package/yast2-rmt.spec 2018-04-24 11:54:43.422604842 +0200
@@ -17,14 +17,14 @@
Name: yast2-rmt
-Version: 0.0.3
+Version: 0.0.4
Release: 0
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Source0: %{name}-%{version}.tar.bz2
-Requires: rmt-server
+Requires: rmt-server >= 0.0.5
Requires: yast2
Requires: yast2-ruby-bindings
@@ -58,6 +58,7 @@
%defattr(-,root,root)
%{yast_dir}/clients/*.rb
%{yast_dir}/lib/rmt
+%{yast_desktopdir}/rmt.desktop
%{yast_dir}/data/rmt
%doc COPYING
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/spec/rmt/ssl/certificate_generator_spec.rb new/yast2-rmt-0.0.4/spec/rmt/ssl/certificate_generator_spec.rb
--- old/yast2-rmt-0.0.3/spec/rmt/ssl/certificate_generator_spec.rb 2018-04-04 15:18:52.421068902 +0200
+++ new/yast2-rmt-0.0.4/spec/rmt/ssl/certificate_generator_spec.rb 2018-04-24 11:54:43.422604842 +0200
@@ -27,10 +27,12 @@
described_class::OPENSSL_FILES.map { |id, filename| [id, File.join(described_class::RMT_SSL_DIR, filename)] }.to_h
end
- let(:crt_and_key_files) { %i[ca_private_key ca_certificate server_private_key server_certificate] }
+ let(:ca_files) { %i[ca_private_key ca_certificate] }
+ let(:server_cert_files) { %i[server_private_key server_certificate] }
+ let(:crt_and_key_files) { ca_files + server_cert_files }
- describe '#check_certs_presence' do
- subject(:result) { generator.check_certs_presence }
+ describe '#ca_present?' do
+ subject(:result) { generator.ca_present? }
before do
# Yast reads locale data at startup for i18n
@@ -38,14 +40,14 @@
end
it 'returns false when none of the files exist' do
- crt_and_key_files.each do |file|
+ ca_files.each do |file|
expect(File).to receive(:exist?).with(ssl_files[file]).and_return(false)
end
expect(result).to eq(false)
end
it 'returns false when all of the files are empty' do
- crt_and_key_files.each do |file|
+ ca_files.each do |file|
expect(File).to receive(:exist?).with(ssl_files[file]).and_return(true)
expect(File).to receive(:zero?).with(ssl_files[file]).and_return(true)
end
@@ -53,7 +55,39 @@
end
it 'returns true when one the files exist and is not empty' do
- file = crt_and_key_files.shift
+ file = ca_files.shift
+ expect(File).to receive(:exist?).with(ssl_files[file]).and_return(true)
+ expect(File).to receive(:zero?).with(ssl_files[file]).and_return(false)
+
+ expect(result).to eq(true)
+ end
+ end
+
+ describe '#server_cert_present??' do
+ subject(:result) { generator.server_cert_present? }
+
+ before do
+ # Yast reads locale data at startup for i18n
+ expect(File).to receive(:exist?).with('/usr/share/YaST2/locale').and_return(false)
+ end
+
+ it 'returns false when none of the files exist' do
+ server_cert_files.each do |file|
+ expect(File).to receive(:exist?).with(ssl_files[file]).and_return(false)
+ end
+ expect(result).to eq(false)
+ end
+
+ it 'returns false when all of the files are empty' do
+ server_cert_files.each do |file|
+ expect(File).to receive(:exist?).with(ssl_files[file]).and_return(true)
+ expect(File).to receive(:zero?).with(ssl_files[file]).and_return(true)
+ end
+ expect(result).to eq(false)
+ end
+
+ it 'returns true when one the files exist and is not empty' do
+ file = server_cert_files.shift
expect(File).to receive(:exist?).with(ssl_files[file]).and_return(true)
expect(File).to receive(:zero?).with(ssl_files[file]).and_return(false)
@@ -71,65 +105,107 @@
let(:common_name) { 'example.org' }
let(:alt_names) { ['foo.example.org', 'bar.example.org'] }
- it 'generates the certificate' do
- expect(RMT::SSL::ConfigGenerator).to receive(:new).and_return(config_generator_double)
- expect(config_generator_double).to receive(:make_ca_config) { ca_config }
- expect(config_generator_double).to receive(:make_server_config) { server_config }
-
- expect(generator).to receive(:create_files)
-
- expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:ca_serial_file], '01')
- expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:ca_config], ca_config)
- expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:server_config], server_config)
-
- expect(RMT::Execute).to receive(:on_target!).with(
- 'openssl', 'genrsa', '-out',
- ssl_files[:ca_private_key], described_class::OPENSSL_KEY_BITS
- )
-
- expect(RMT::Execute).to receive(:on_target!).with(
- 'openssl', 'genrsa', '-out',
- ssl_files[:server_private_key], described_class::OPENSSL_KEY_BITS
- )
-
- expect(RMT::Execute).to receive(:on_target!).with(
- 'openssl', 'req', '-x509', '-new', '-nodes',
- '-key', ssl_files[:ca_private_key], '-sha256', '-days', described_class::OPENSSL_CA_VALIDITY_DAYS,
- '-out', ssl_files[:ca_certificate], '-config', ssl_files[:ca_config]
- )
-
- expect(RMT::Execute).to receive(:on_target!).with(
- 'openssl', 'req', '-new', '-key', ssl_files[:server_private_key],
- '-out', ssl_files[:server_csr], '-config', ssl_files[:server_config]
- )
-
- expect(RMT::Execute).to receive(:on_target!).with(
- 'openssl', 'x509', '-req', '-in', ssl_files[:server_csr],
- '-out', ssl_files[:server_certificate], '-CA', ssl_files[:ca_certificate],
- '-CAkey', ssl_files[:ca_private_key], '-days', described_class::OPENSSL_SERVER_CERT_VALIDITY_DAYS,
- '-sha256', '-CAcreateserial', '-extensions', 'v3_server_sign',
- '-extfile', ssl_files[:server_config]
- )
-
- expect(Yast::SCR).to receive(:Read).with(scr_path, ssl_files[:server_certificate]).and_return(server_cert)
- expect(Yast::SCR).to receive(:Read).with(scr_path, ssl_files[:ca_certificate]).and_return(ca_cert)
- expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:server_certificate], server_cert + ca_cert)
+ context 'when CA is not yet generated' do
+ it 'generates the CA and server certificates' do
+ expect(RMT::SSL::ConfigGenerator).to receive(:new).and_return(config_generator_double)
+ expect(generator).to receive(:ca_present?).and_return(false).exactly(2).times
+ expect(config_generator_double).to receive(:make_ca_config).and_return(ca_config)
+ expect(config_generator_double).to receive(:make_server_config).and_return(server_config)
+
+ expect(generator).to receive(:create_files)
+
+ expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:ca_serial_file], '01')
+ expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:ca_config], ca_config)
+ expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:server_config], server_config)
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'genrsa', '-out',
+ ssl_files[:ca_private_key], described_class::OPENSSL_KEY_BITS
+ )
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'genrsa', '-out',
+ ssl_files[:server_private_key], described_class::OPENSSL_KEY_BITS
+ )
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'req', '-x509', '-new', '-nodes',
+ '-key', ssl_files[:ca_private_key], '-sha256', '-days', described_class::OPENSSL_CA_VALIDITY_DAYS,
+ '-out', ssl_files[:ca_certificate], '-config', ssl_files[:ca_config]
+ )
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'req', '-new', '-key', ssl_files[:server_private_key],
+ '-out', ssl_files[:server_csr], '-config', ssl_files[:server_config]
+ )
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'x509', '-req', '-in', ssl_files[:server_csr],
+ '-out', ssl_files[:server_certificate], '-CA', ssl_files[:ca_certificate],
+ '-CAkey', ssl_files[:ca_private_key], '-days', described_class::OPENSSL_SERVER_CERT_VALIDITY_DAYS,
+ '-sha256', '-CAcreateserial', '-extensions', 'v3_server_sign',
+ '-extfile', ssl_files[:server_config]
+ )
+
+ expect(Yast::SCR).to receive(:Read).with(scr_path, ssl_files[:server_certificate]).and_return(server_cert)
+ expect(Yast::SCR).to receive(:Read).with(scr_path, ssl_files[:ca_certificate]).and_return(ca_cert)
+ expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:server_certificate], server_cert + ca_cert)
- expect(RMT::Execute).to receive(:on_target!).with('chown', 'root:nginx', ssl_files[:ca_certificate])
- expect(RMT::Execute).to receive(:on_target!).with('chmod', '0640', ssl_files[:ca_certificate])
+ expect(RMT::Execute).to receive(:on_target!).with('chown', 'root:nginx', ssl_files[:ca_certificate])
+ expect(RMT::Execute).to receive(:on_target!).with('chmod', '0640', ssl_files[:ca_certificate])
- generator.generate(common_name, alt_names)
+ generator.generate(common_name, alt_names)
+ end
+ end
+
+ context 'when CA is already present' do
+ it 'generates only the server certificate' do
+ expect(RMT::SSL::ConfigGenerator).to receive(:new).and_return(config_generator_double)
+ expect(generator).to receive(:ca_present?).and_return(true).exactly(2).times
+ expect(config_generator_double).to receive(:make_server_config).and_return(server_config)
+
+ expect(generator).to receive(:create_files)
+
+ expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:server_config], server_config)
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'genrsa', '-out',
+ ssl_files[:server_private_key], described_class::OPENSSL_KEY_BITS
+ )
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'req', '-new', '-key', ssl_files[:server_private_key],
+ '-out', ssl_files[:server_csr], '-config', ssl_files[:server_config]
+ )
+
+ expect(RMT::Execute).to receive(:on_target!).with(
+ 'openssl', 'x509', '-req', '-in', ssl_files[:server_csr],
+ '-out', ssl_files[:server_certificate], '-CA', ssl_files[:ca_certificate],
+ '-CAkey', ssl_files[:ca_private_key], '-days', described_class::OPENSSL_SERVER_CERT_VALIDITY_DAYS,
+ '-sha256', '-CAcreateserial', '-extensions', 'v3_server_sign',
+ '-extfile', ssl_files[:server_config]
+ )
+
+ expect(Yast::SCR).to receive(:Read).with(scr_path, ssl_files[:server_certificate]).and_return(server_cert)
+ expect(Yast::SCR).to receive(:Read).with(scr_path, ssl_files[:ca_certificate]).and_return(ca_cert)
+ expect(Yast::SCR).to receive(:Write).with(scr_path, ssl_files[:server_certificate], server_cert + ca_cert)
+
+ expect(RMT::Execute).to receive(:on_target!).with('chown', 'root:nginx', ssl_files[:ca_certificate])
+ expect(RMT::Execute).to receive(:on_target!).with('chmod', '0640', ssl_files[:ca_certificate])
+
+ generator.generate(common_name, alt_names)
+ end
end
it 'handles Cheetah::ExecutionFailed exceptions' do
expect(RMT::SSL::ConfigGenerator).to receive(:new).and_raise(Cheetah::ExecutionFailed.new('cmd', 1, '', 'Dummy error'))
- expect(Yast::Report).to receive(:Error).with("An error ocurred during SSL certificate generation:\nDummy error\n")
+ expect(Yast::Report).to receive(:Error).with("An error occurred during SSL certificate generation:\nDummy error\n")
generator.generate(common_name, alt_names)
end
it 'handles RMT::SSL::Exception exceptions' do
expect(RMT::SSL::ConfigGenerator).to receive(:new).and_raise(RMT::SSL::Exception.new('Dummy error'))
- expect(Yast::Report).to receive(:Error).with("An error ocurred during SSL certificate generation:\nDummy error\n")
+ expect(Yast::Report).to receive(:Error).with("An error occurred during SSL certificate generation:\nDummy error\n")
generator.generate(common_name, alt_names)
end
end
@@ -140,7 +216,7 @@
expect(generator).to receive(:write_file).with(file, '')
expect(RMT::Execute).to receive(:on_target!).with('chmod', '0600', file)
end
- generator.send(:create_files)
+ generator.send(:create_files, ssl_files)
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/spec/rmt/ssl/config_generator_spec.rb new/yast2-rmt-0.0.4/spec/rmt/ssl/config_generator_spec.rb
--- old/yast2-rmt-0.0.3/spec/rmt/ssl/config_generator_spec.rb 2018-04-04 13:29:22.681899544 +0200
+++ new/yast2-rmt-0.0.4/spec/rmt/ssl/config_generator_spec.rb 2018-04-24 11:54:43.422604842 +0200
@@ -25,6 +25,8 @@
let(:dns_names) { ['foo.example.org', 'bar.example.org'] }
let(:ip_addresses) { ['1.1.1.1', '1111:2222:3333:4444:5555:6666:7777:8888'] }
let(:alt_names) { dns_names + ip_addresses }
+ let(:template_system_location) { File.join(File.expand_path('./../../../src/data/rmt', __dir__), template_filename) }
+ let(:template) { File.read(File.join('src/data/rmt', template_filename)) }
describe '#new' do
it 'matches DNS names' do
@@ -37,25 +39,38 @@
end
describe '#make_ca_config' do
+ let(:template_filename) { 'rmt-ca.cnf.erb' }
+
it 'contains correct common name' do
+ expect(File).to receive(:read).with(template_system_location).and_return(template)
expect(generator.make_ca_config).to match(/CN\s*=\s*RMT Certificate Authority \(#{common_name}\)/)
end
+
+ it 'writes to correct file' do
+ expect(File).to receive(:read).with(template_system_location).and_return(template)
+ generator.make_ca_config
+ end
end
describe '#make_server_config' do
subject(:config) { generator.make_server_config }
+ let(:template_filename) { 'rmt-server-cert.cnf.erb' }
+
it 'contains correct common name' do
+ expect(File).to receive(:read).with(template_system_location).and_return(template)
expect(config).to match(/CN\s*=\s*#{common_name}/)
end
it 'contains DNS alternative common names' do
+ expect(File).to receive(:read).with(template_system_location).and_return(template)
dns_names.each do |alt_name|
expect(config).to match(/DNS\.\d+\s*=\s*#{alt_name}/)
end
end
it 'contains IP alternative common names' do
+ expect(File).to receive(:read).with(template_system_location).and_return(template)
ip_addresses.each do |alt_name|
expect(config).to match(/IP\.\d+\s*=\s*#{alt_name}/)
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/spec/rmt/wizard_final_page_spec.rb new/yast2-rmt-0.0.4/spec/rmt/wizard_final_page_spec.rb
--- old/yast2-rmt-0.0.3/spec/rmt/wizard_final_page_spec.rb 1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-rmt-0.0.4/spec/rmt/wizard_final_page_spec.rb 2018-04-16 15:10:34.949032563 +0200
@@ -0,0 +1,78 @@
+# Copyright (c) 2018 SUSE LLC.
+# All Rights Reserved.
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 or 3 of the GNU General
+# Public License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, contact SUSE LLC.
+
+# To contact SUSE about this file by physical or electronic mail,
+# you may find current contact information at www.suse.com
+
+require 'rmt/wizard_final_page'
+
+Yast.import 'Wizard'
+
+describe RMT::WizardFinalPage do
+ subject(:final_page) { described_class.new(config) }
+
+ let(:config) { {} }
+
+ describe '#next_handler' do
+ it 'finishes when next button is pressed' do
+ expect(final_page).to receive(:finish_dialog).with(:next)
+ final_page.next_handler
+ end
+ end
+
+ describe '#abort_handler' do
+ it 'finishes when abort button is pressed' do
+ expect(final_page).to receive(:finish_dialog).with(:abort)
+ final_page.abort_handler
+ end
+ end
+
+ describe '#back_handler' do
+ it 'finishes when back button is pressed' do
+ expect(final_page).to receive(:finish_dialog).with(:back)
+ final_page.back_handler
+ end
+ end
+
+ describe '#render_content' do
+ it 'renders UI elements' do
+ expect(Yast::Wizard).to receive(:SetContents)
+ final_page.render_content
+ end
+ end
+
+ describe '#run' do
+ context 'when restarting the service succeeds' do
+ it 'renders content and enters the event loop' do
+ expect(Yast::Service).to receive(:Enable).with('rmt').and_return(true)
+ expect(Yast::Service).to receive(:Restart).with('rmt').and_return(true)
+ expect(final_page).to receive(:render_content)
+ expect(final_page).to receive(:event_loop)
+ final_page.run
+ end
+ end
+
+ context 'when restarting the service fails' do
+ it 'displays the error, renders content and enters the event loop' do
+ expect(Yast::Service).to receive(:Enable).with('rmt').and_return(true)
+ expect(Yast::Service).to receive(:Restart).with('rmt').and_return(false)
+ expect(Yast::Report).to receive(:Error).with("Failed to enable and restart service 'rmt'")
+ expect(final_page).to receive(:render_content)
+ expect(final_page).to receive(:event_loop)
+ final_page.run
+ end
+ end
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/spec/rmt/wizard_maria_db_page_spec.rb new/yast2-rmt-0.0.4/spec/rmt/wizard_maria_db_page_spec.rb
--- old/yast2-rmt-0.0.3/spec/rmt/wizard_maria_db_page_spec.rb 2018-04-04 15:27:00.475284854 +0200
+++ new/yast2-rmt-0.0.4/spec/rmt/wizard_maria_db_page_spec.rb 2018-04-16 15:10:34.949032563 +0200
@@ -25,7 +25,16 @@
describe RMT::WizardMariaDBPage do
subject(:mariadb_page) { described_class.new(config) }
- let(:config) { { 'database' => { 'username' => 'user_mcuserface', 'password' => 'test' } } }
+ let(:config) do
+ {
+ 'database' => {
+ 'username' => 'user_mcuserface',
+ 'password' => 'test',
+ 'hostname' => 'localhost',
+ 'database' => 'rmt'
+ }
+ }
+ end
describe '#render_content' do
it 'renders UI elements' do
@@ -40,11 +49,19 @@
end
describe '#run' do
- it 'renders content and runs the event loop' do
+ it 'renders content and runs the event loop when the DB is not set up' do
+ expect(mariadb_page).to receive(:check_db_credentials).and_return(false)
expect(mariadb_page).to receive(:render_content)
expect(mariadb_page).to receive(:event_loop)
mariadb_page.run
end
+
+ it 'skips DB creation when DB is already set up' do
+ expect(mariadb_page).to receive(:check_db_credentials).and_return(true)
+ expect(Yast::Popup).to receive(:Message).with('Database has already been configured, skipping database setup.')
+ expect(mariadb_page).to receive(:finish_dialog).with(:next)
+ mariadb_page.run
+ end
end
describe '#abort_handler' do
@@ -187,4 +204,38 @@
expect(mariadb_page.create_database_and_user).to be(true)
end
end
+
+ describe '#check_db_credentials' do
+ context 'when the required configuration keys are missing in the DB section' do
+ let(:config) { { 'database' => {} } }
+
+ it('returns false') { expect(mariadb_page.check_db_credentials).to be(false) }
+ end
+
+ context 'when the required configuration keys are present and are invalid' do
+ it 'returns false' do
+ expect(RMT::Execute).to receive(:on_target!).with(
+ ['echo', 'select 1;'],
+ [
+ 'mysql', '-u', config['database']['username'], "-p#{config['database']['password']}",
+ '-D', config['database']['database'], '-h', config['database']['hostname']
+ ]
+ ).and_raise(Cheetah::ExecutionFailed.new('command', 255, '', 'Something went wrong'))
+ expect(mariadb_page.check_db_credentials).to be(false)
+ end
+ end
+
+ context 'when the required configuration keys are present and are valid' do
+ it 'returns false' do
+ expect(RMT::Execute).to receive(:on_target!).with(
+ ['echo', 'select 1;'],
+ [
+ 'mysql', '-u', config['database']['username'], "-p#{config['database']['password']}",
+ '-D', config['database']['database'], '-h', config['database']['hostname']
+ ]
+ )
+ expect(mariadb_page.check_db_credentials).to be(true)
+ end
+ end
+ end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/spec/rmt/wizard_spec.rb new/yast2-rmt-0.0.4/spec/rmt/wizard_spec.rb
--- old/yast2-rmt-0.0.3/spec/rmt/wizard_spec.rb 2018-03-27 15:39:21.355318371 +0200
+++ new/yast2-rmt-0.0.4/spec/rmt/wizard_spec.rb 2018-04-16 15:10:34.949032563 +0200
@@ -29,6 +29,7 @@
let(:scc_page_double) { instance_double(RMT::WizardSCCPage) }
let(:db_page_double) { instance_double(RMT::WizardMariaDBPage) }
let(:ssl_page_double) { instance_double(RMT::WizardSSLPage) }
+ let(:final_page_double) { instance_double(RMT::WizardFinalPage) }
it 'runs and goes through the sequence' do
expect(Yast::Confirm).to receive(:MustBeRoot).and_return(true)
@@ -46,6 +47,9 @@
expect(RMT::WizardSSLPage).to receive(:new).and_return(ssl_page_double)
expect(ssl_page_double).to receive(:run).and_return(:next)
+ expect(RMT::WizardFinalPage).to receive(:new).and_return(final_page_double)
+ expect(final_page_double).to receive(:run).and_return(:next)
+
expect(Yast::UI).to receive(:CloseDialog)
wizard.run
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/spec/rmt/wizard_ssl_page_spec.rb new/yast2-rmt-0.0.4/spec/rmt/wizard_ssl_page_spec.rb
--- old/yast2-rmt-0.0.3/spec/rmt/wizard_ssl_page_spec.rb 2018-04-04 15:27:08.159320139 +0200
+++ new/yast2-rmt-0.0.4/spec/rmt/wizard_ssl_page_spec.rb 2018-04-24 11:54:43.422604842 +0200
@@ -36,7 +36,6 @@
describe '#render_content' do
it 'renders UI elements' do
- expect(Yast::Wizard).to receive(:SetNextButton).with(:next, Yast::Label.FinishButton)
expect(Yast::Wizard).to receive(:SetContents)
expect(ssl_page).to receive(:query_common_name)
@@ -118,7 +117,7 @@
describe '#run' do
context 'when certificates are already present' do
it 'shows a message and finishes' do
- expect(generator_double).to receive(:check_certs_presence).and_return(true)
+ expect(generator_double).to receive(:server_cert_present?).and_return(true)
expect(Yast::Popup).to receive(:Message).with('SSL certificates already present, skipping generation.')
expect(ssl_page).to receive(:finish_dialog).with(:next)
ssl_page.run
@@ -127,7 +126,7 @@
context 'when certificates are not present' do
it 'renders content and enters the event loop' do
- expect(generator_double).to receive(:check_certs_presence).and_return(false)
+ expect(generator_double).to receive(:server_cert_present?).and_return(false)
expect(ssl_page).to receive(:render_content)
expect(ssl_page).to receive(:event_loop)
ssl_page.run
@@ -140,6 +139,13 @@
expect(RMT::Execute).to receive(:on_target!).with('hostname', '--long', stdout: :capture).and_return("\n\n\nexample.org\n\n")
expect(ssl_page.send(:query_common_name)).to eq('example.org')
end
+
+ it 'handles exceptions and sets the default common name' do
+ expect(RMT::Execute).to receive(:on_target!).with('hostname', '--long', stdout: :capture).and_raise(
+ Cheetah::ExecutionFailed.new('command', 255, '', 'Something went wrong')
+ )
+ expect(ssl_page.send(:query_common_name)).to eq('rmt.server')
+ end
end
describe '#query_alt_names' do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/desktop/rmt.desktop new/yast2-rmt-0.0.4/src/desktop/rmt.desktop
--- old/yast2-rmt-0.0.3/src/desktop/rmt.desktop 1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-rmt-0.0.4/src/desktop/rmt.desktop 2018-04-18 11:54:50.762844172 +0200
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Type=Application
+Categories=Settings;System;Qt;X-SuSE-YaST;X-SuSE-YaST-Support;
+
+X-SuSE-YaST-Call=rmt
+X-SuSE-YaST-RootOnly=true
+X-SuSE-YaST-Group=Net_advanced
+X-SuSE-YaST-AutoInst=
+X-SuSE-YaST-AutoInstResource=rmt
+
+Icon=yast-rmt
+Exec=/sbin/yast2 rmt
+
+Name=RMT Configuration
+GenericName=RMT Configuration
+StartupNotify=true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/lib/rmt/ssl/certificate_generator.rb new/yast2-rmt-0.0.4/src/lib/rmt/ssl/certificate_generator.rb
--- old/yast2-rmt-0.0.3/src/lib/rmt/ssl/certificate_generator.rb 2018-04-04 15:17:14.972628767 +0200
+++ new/yast2-rmt-0.0.4/src/lib/rmt/ssl/certificate_generator.rb 2018-04-24 11:54:43.426604857 +0200
@@ -51,32 +51,43 @@
@ssl_paths = OPENSSL_FILES.map { |id, filename| [id, File.join(RMT_SSL_DIR, filename)] }.to_h
end
- def check_certs_presence
- %i[ca_private_key ca_certificate server_private_key server_certificate].each do |file_type|
+ def ca_present?
+ %i[ca_private_key ca_certificate].each do |file_type|
return true if File.exist?(@ssl_paths[file_type]) && !File.zero?(@ssl_paths[file_type])
end
+ false
+ end
+ def server_cert_present?
+ %i[server_private_key server_certificate].each do |file_type|
+ return true if File.exist?(@ssl_paths[file_type]) && !File.zero?(@ssl_paths[file_type])
+ end
false
end
def generate(common_name, alt_names)
config_generator = RMT::SSL::ConfigGenerator.new(common_name, alt_names)
- create_files
+ files = @ssl_paths.dup
+ %i[ca_certificate ca_private_key ca_serial_file ca_config].each { |file| files.delete(file) } if ca_present?
- Yast::SCR.Write(Yast.path('.target.string'), @ssl_paths[:ca_serial_file], '01')
- Yast::SCR.Write(Yast.path('.target.string'), @ssl_paths[:ca_config], config_generator.make_ca_config)
- Yast::SCR.Write(Yast.path('.target.string'), @ssl_paths[:server_config], config_generator.make_server_config)
+ create_files(files)
- RMT::Execute.on_target!('openssl', 'genrsa', '-out', @ssl_paths[:ca_private_key], OPENSSL_KEY_BITS)
- RMT::Execute.on_target!('openssl', 'genrsa', '-out', @ssl_paths[:server_private_key], OPENSSL_KEY_BITS)
+ Yast::SCR.Write(Yast.path('.target.string'), @ssl_paths[:server_config], config_generator.make_server_config)
- RMT::Execute.on_target!(
- 'openssl', 'req', '-x509', '-new', '-nodes', '-key', @ssl_paths[:ca_private_key],
- '-sha256', '-days', OPENSSL_CA_VALIDITY_DAYS, '-out', @ssl_paths[:ca_certificate],
- '-config', @ssl_paths[:ca_config]
- )
+ unless ca_present?
+ Yast::SCR.Write(Yast.path('.target.string'), @ssl_paths[:ca_serial_file], '01')
+ Yast::SCR.Write(Yast.path('.target.string'), @ssl_paths[:ca_config], config_generator.make_ca_config)
+
+ RMT::Execute.on_target!('openssl', 'genrsa', '-out', @ssl_paths[:ca_private_key], OPENSSL_KEY_BITS)
+ RMT::Execute.on_target!(
+ 'openssl', 'req', '-x509', '-new', '-nodes', '-key', @ssl_paths[:ca_private_key],
+ '-sha256', '-days', OPENSSL_CA_VALIDITY_DAYS, '-out', @ssl_paths[:ca_certificate],
+ '-config', @ssl_paths[:ca_config]
+ )
+ end
+ RMT::Execute.on_target!('openssl', 'genrsa', '-out', @ssl_paths[:server_private_key], OPENSSL_KEY_BITS)
RMT::Execute.on_target!(
'openssl', 'req', '-new', '-key', @ssl_paths[:server_private_key],
'-out', @ssl_paths[:server_csr], '-config', @ssl_paths[:server_config]
@@ -101,7 +112,7 @@
rescue Cheetah::ExecutionFailed, RMT::SSL::Exception => e
Yast.import 'Report'
Yast::Report.Error(
- _("An error ocurred during SSL certificate generation:\n%<error>s\n") % {
+ _("An error occurred during SSL certificate generation:\n%<error>s\n") % {
error: (e.class == Cheetah::ExecutionFailed) ? e.stderr : e.to_s
}
)
@@ -110,8 +121,8 @@
protected
# Creates empty files and sets 600 permissions
- def create_files
- @ssl_paths.each_value do |file|
+ def create_files(files)
+ files.each_value do |file|
write_file(file, '')
RMT::Execute.on_target!('chmod', '0600', file)
end
@@ -119,6 +130,6 @@
def write_file(filename, content)
result = Yast::SCR.Write(Yast.path('.target.string'), filename, content)
- raise RMT::SSL::Exception, "Failed to write file #{filename}" unless result
+ raise RMT::SSL::Exception, _('Failed to write file %<filename>s' % { filename: filename }) unless result
end
end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/lib/rmt/wizard.rb new/yast2-rmt-0.0.4/src/lib/rmt/wizard.rb
--- old/yast2-rmt-0.0.3/src/lib/rmt/wizard.rb 2018-04-04 15:21:33.149795816 +0200
+++ new/yast2-rmt-0.0.4/src/lib/rmt/wizard.rb 2018-04-16 15:10:34.949032563 +0200
@@ -20,6 +20,7 @@
require 'rmt/wizard_scc_page'
require 'rmt/wizard_maria_db_page'
require 'rmt/wizard_ssl_page'
+require 'rmt/wizard_final_page'
module RMT
end
@@ -47,14 +48,16 @@
aliases = {
'step1' => -> { RMT::WizardSCCPage.new(@config).run },
'step2' => -> { RMT::WizardMariaDBPage.new(@config).run },
- 'step3' => -> { RMT::WizardSSLPage.new(@config).run }
+ 'step3' => -> { RMT::WizardSSLPage.new(@config).run },
+ 'finish' => -> { RMT::WizardFinalPage.new(@config).run }
}
sequence = {
'ws_start' => 'step1',
'step1' => { abort: :abort, next: 'step2' },
'step2' => { abort: :abort, next: 'step3' },
- 'step3' => { abort: :abort, next: :next }
+ 'step3' => { abort: :abort, next: 'finish' },
+ 'finish' => { abort: :abort, next: :next }
}
Wizard.CreateDialog()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/lib/rmt/wizard_final_page.rb new/yast2-rmt-0.0.4/src/lib/rmt/wizard_final_page.rb
--- old/yast2-rmt-0.0.3/src/lib/rmt/wizard_final_page.rb 1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-rmt-0.0.4/src/lib/rmt/wizard_final_page.rb 2018-04-16 15:10:34.949032563 +0200
@@ -0,0 +1,74 @@
+# Copyright (c) 2018 SUSE LLC.
+# All Rights Reserved.
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of version 2 or 3 of the GNU General
+# Public License as published by the Free Software Foundation.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, contact SUSE LLC.
+
+# To contact SUSE about this file by physical or electronic mail,
+# you may find current contact information at www.suse.com
+
+require 'ui/event_dispatcher'
+
+module RMT; end
+
+class RMT::WizardFinalPage < Yast::Client
+ include ::UI::EventDispatcher
+
+ Yast.import 'Report'
+ Yast.import 'Service'
+
+ def initialize(config)
+ textdomain 'rmt'
+ @config = config
+ end
+
+ def render_content
+ Wizard.SetNextButton(:next, Label.FinishButton)
+
+ contents =
+ HBox(
+ HSpacing(1),
+ VBox(
+ VSpacing(1),
+ Label(_('RMT setup is now complete.')),
+ VSpacing(1)
+ ),
+ HSpacing(1)
+ )
+
+ Wizard.SetContents(
+ _('RMT configuration'),
+ contents,
+ _('<p>RMT setup is now complete.</p>'),
+ true,
+ true
+ )
+ end
+
+ def next_handler
+ finish_dialog(:next)
+ end
+
+ def abort_handler
+ finish_dialog(:abort)
+ end
+
+ def back_handler
+ finish_dialog(:back)
+ end
+
+ def run
+ Yast::Report.Error(_("Failed to enable and restart service 'rmt'")) unless (Yast::Service.Enable('rmt') && Yast::Service.Restart('rmt'))
+ render_content
+ event_loop
+ end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/lib/rmt/wizard_maria_db_page.rb new/yast2-rmt-0.0.4/src/lib/rmt/wizard_maria_db_page.rb
--- old/yast2-rmt-0.0.3/src/lib/rmt/wizard_maria_db_page.rb 2018-04-04 15:26:06.627037592 +0200
+++ new/yast2-rmt-0.0.4/src/lib/rmt/wizard_maria_db_page.rb 2018-04-16 15:10:34.949032563 +0200
@@ -18,6 +18,7 @@
require 'rmt/maria_db/current_root_password_dialog'
require 'rmt/maria_db/new_root_password_dialog'
+require 'rmt/execute'
require 'ui/event_dispatcher'
module RMT; end
@@ -53,7 +54,7 @@
Wizard.SetContents(
_('RMT configuration step 2/3'),
contents,
- '<p>This step of the wizard performs the necessary database setup.</p>',
+ _('<p>This step of the wizard performs the necessary database setup.</p>'),
true,
true
)
@@ -81,7 +82,7 @@
new_root_password = dialog.run
if !new_root_password || new_root_password.empty? || !dialog.set_root_password(new_root_password, @config['database']['hostname'])
- Report.Error('Setting new root password failed')
+ Report.Error(_('Setting new root password failed'))
return
end
@@ -94,7 +95,7 @@
if @root_password
create_database_and_user
else
- Report.Error('Root password not provided, skipping database setup.')
+ Report.Error(_('Root password not provided, skipping database setup.'))
end
RMT::Utils.write_config_file(@config)
@@ -102,10 +103,31 @@
end
def run
+ if check_db_credentials
+ Yast::Popup.Message(_('Database has already been configured, skipping database setup.'))
+ return finish_dialog(:next)
+ end
render_content
event_loop
end
+ def check_db_credentials
+ %w[username password database hostname].each do |key|
+ return false if (!@config['database'][key] || @config['database'][key].empty?)
+ end
+
+ RMT::Execute.on_target!(
+ ['echo', 'select 1;'],
+ [
+ 'mysql', '-u', @config['database']['username'], "-p#{@config['database']['password']}",
+ '-D', @config['database']['database'], '-h', @config['database']['hostname']
+ ]
+ )
+ true
+ rescue Cheetah::ExecutionFailed
+ false
+ end
+
def root_password_empty?
RMT::Utils.run_command(
"echo 'show databases;' | mysql -u root -h %1 2>/dev/null",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/lib/rmt/wizard_scc_page.rb new/yast2-rmt-0.0.4/src/lib/rmt/wizard_scc_page.rb
--- old/yast2-rmt-0.0.3/src/lib/rmt/wizard_scc_page.rb 2018-04-04 15:26:11.315059118 +0200
+++ new/yast2-rmt-0.0.4/src/lib/rmt/wizard_scc_page.rb 2018-04-16 15:10:34.949032563 +0200
@@ -56,7 +56,7 @@
Wizard.SetContents(
_('RMT configuration step 1/3'),
contents,
- "<p>Organization credentials can be found on Organization page at <a href='https://scc.suse.com/'>SUSE Customer Center</a>.</p>",
+ _("<p>Organization credentials can be found on Organization page at <a href='https://scc.suse.com/'>SUSE Customer Center</a>.</p>"),
true,
true
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yast2-rmt-0.0.3/src/lib/rmt/wizard_ssl_page.rb new/yast2-rmt-0.0.4/src/lib/rmt/wizard_ssl_page.rb
--- old/yast2-rmt-0.0.3/src/lib/rmt/wizard_ssl_page.rb 2018-04-04 15:24:17.146538672 +0200
+++ new/yast2-rmt-0.0.4/src/lib/rmt/wizard_ssl_page.rb 2018-04-24 11:54:43.450604946 +0200
@@ -65,11 +65,10 @@
)
)
- Wizard.SetNextButton(:next, Label.FinishButton)
Wizard.SetContents(
_('RMT configuration step 3/3'),
contents,
- '<p>This step of the wizard generates the required SSL certificates.</p>',
+ _('<p>This step of the wizard generates the required SSL certificates.</p>'),
true,
true
)
@@ -117,8 +116,8 @@
end
def run
- if @cert_generator.check_certs_presence
- Yast::Popup.Message('SSL certificates already present, skipping generation.')
+ if @cert_generator.server_cert_present?
+ Yast::Popup.Message(_('SSL certificates already present, skipping generation.'))
return finish_dialog(:next)
end
render_content
@@ -130,6 +129,8 @@
def query_common_name
output = RMT::Execute.on_target!('hostname', '--long', stdout: :capture)
output.strip
+ rescue Cheetah::ExecutionFailed
+ 'rmt.server'
end
def query_alt_names
1
0
Hello community,
here is the log from the commit of package python-curtsies for openSUSE:Factory checked in at 2018-04-27 16:09:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-curtsies (Old)
and /work/SRC/openSUSE:Factory/.python-curtsies.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-curtsies"
Fri Apr 27 16:09:14 2018 rev:4 rq:601624 version:0.3.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-curtsies/python-curtsies.changes 2018-02-22 15:02:46.437296097 +0100
+++ /work/SRC/openSUSE:Factory/.python-curtsies.new/python-curtsies.changes 2018-04-27 16:09:15.958414786 +0200
@@ -1,0 +2,7 @@
+Thu Apr 26 14:30:25 UTC 2018 - badshah400(a)opensuse.org
+
+- Add python-curtsies-dont-require-typing-for-python3.5.patch: The
+ typing module is only required for python3.4 and lower; patch
+ taken from upstream git (gh#bpython/curtsies#111).
+
+-------------------------------------------------------------------
New:
----
python-curtsies-dont-require-typing-for-python3.5.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-curtsies.spec ++++++
--- /var/tmp/diff_new_pack.divtmX/_old 2018-04-27 16:09:16.450396742 +0200
+++ /var/tmp/diff_new_pack.divtmX/_new 2018-04-27 16:09:16.454396596 +0200
@@ -23,8 +23,10 @@
Summary: Curses-like terminal wrapper, with colored strings!
License: MIT
Group: Development/Languages/Python
-Url: https://github.com/bpython/curtsies
+URL: https://github.com/bpython/curtsies
Source: https://files.pythonhosted.org/packages/source/c/curtsies/curtsies-%{versio…
+# PATCH-FIX-UPSTREAM python-curtsies-dont-require-typing-for-python3.5.patch gh#bpython/curtsies#111 badshah400(a)opensuse.org -- The typing module is only required for python3.4 and lower; patch taken from upstream git.
+Patch0: python-curtsies-dont-require-typing-for-python3.5.patch
BuildRequires: %{python_module blessings}
BuildRequires: %{python_module devel}
BuildRequires: %{python_module mock}
@@ -34,12 +36,12 @@
BuildRequires: fdupes
BuildRequires: python-rpm-macros
BuildRequires: python2-typing
+Requires: python-blessings
+BuildArch: noarch
# do not require python3-typing for python >= 3.5
%if 0%{?suse_version} <= 1320
BuildRequires: python3-typing
%endif
-
-Requires: python-blessings
%ifpython2
Requires: python-typing
%endif
@@ -48,9 +50,6 @@
Requires: python-typing
%endif
%endif
-
-BuildArch: noarch
-
%python_subpackages
%description
@@ -59,6 +58,7 @@
%prep
%setup -q -n curtsies-%{version}
+%patch0 -p1
%build
%python_build
@@ -71,8 +71,8 @@
%python_expand nosetests-%{$python_bin_suffix}
%files %{python_files}
-%defattr(-,root,root,-)
-%doc readme.md LICENSE
+%license LICENSE
+%doc readme.md
%{python_sitelib}/*
%changelog
++++++ python-curtsies-dont-require-typing-for-python3.5.patch ++++++
>From 217b4f83e954837f8adc4c549c1f2f9f2bb272a7 Mon Sep 17 00:00:00 2001
From: Po-Chuan Hsieh <sunpoet(a)sunpoet.net>
Date: Wed, 14 Feb 2018 21:28:38 +0800
Subject: [PATCH] Fix install_requires
typing is only required for Python 3.4 or below.
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index b35c7c3..6e52cbd 100644
--- a/setup.py
+++ b/setup.py
@@ -41,7 +41,7 @@ def get_long_description():
install_requires = [
'blessings>=1.5',
'wcwidth>=0.1.4',
- 'typing',
+ 'typing; python_version<"3.5"',
],
tests_require = [
'mock',
1
0
Hello community,
here is the log from the commit of package mkdud for openSUSE:Factory checked in at 2018-04-27 16:09:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/mkdud (Old)
and /work/SRC/openSUSE:Factory/.mkdud.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mkdud"
Fri Apr 27 16:09:12 2018 rev:21 rq:601617 version:1.34
Changes:
--------
--- /work/SRC/openSUSE:Factory/mkdud/mkdud.changes 2018-04-11 14:03:27.507621682 +0200
+++ /work/SRC/openSUSE:Factory/.mkdud.new/mkdud.changes 2018-04-27 16:09:15.222441779 +0200
@@ -1,0 +2,14 @@
+Thu Apr 26 14:23:20 UTC 2018 - wfeldt(a)opensuse.org
+
+- merge gh#openSUSE/mkdud#14
+- fix Makefile and update git2log script
+- 1.34
+
+--------------------------------------------------------------------
+Thu Apr 26 14:20:34 UTC 2018 - wfeldt(a)opensuse.org
+
+- merge gh#openSUSE/mkdud#13
+- improve documentation
+- 1.33
+
+--------------------------------------------------------------------
Old:
----
mkdud-1.32.tar.xz
New:
----
mkdud-1.34.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ mkdud.spec ++++++
--- /var/tmp/diff_new_pack.yauEMp/_old 2018-04-27 16:09:15.766421828 +0200
+++ /var/tmp/diff_new_pack.yauEMp/_new 2018-04-27 16:09:15.770421681 +0200
@@ -23,7 +23,7 @@
Summary: Create driver update from rpms
License: GPL-3.0+
Group: Hardware/Other
-Version: 1.32
+Version: 1.34
Release: 0
Source: %{name}-%{version}.tar.xz
Url: https://github.com/wfeldt/mkdud
++++++ mkdud-1.32.tar.xz -> mkdud-1.34.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mkdud-1.32/Makefile new/mkdud-1.34/Makefile
--- old/mkdud-1.32/Makefile 2018-04-10 10:20:24.000000000 +0200
+++ new/mkdud-1.34/Makefile 2018-04-26 16:23:20.000000000 +0200
@@ -24,5 +24,5 @@
@rm -f mkdud.tmp
clean:
- @rm -rf *~ package
+ @rm -rf *~ package changelog VERSION
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mkdud-1.32/README.md new/mkdud-1.34/README.md
--- old/mkdud-1.32/README.md 2018-04-10 10:20:24.000000000 +0200
+++ new/mkdud-1.34/README.md 2018-04-26 16:23:20.000000000 +0200
@@ -1,9 +1,17 @@
# mkdud
+## About
+
This is about driver updates. If you're not familiar with them, please look at
http://ftp.suse.com/pub/people/hvogel/Update-Media-HOWTO/index.html and
http://en.opensuse.org/SDB:Linuxrc#p_driverupdate first.
+`mkdud` is a tool that makes it easy to create driver updates for SUSE distributions.
+
+## Downloads
+
+Get the latest version from the [openSUSE Build Service](https://software.opensuse.org/package/mkdud).
+
## Usage
### Updating RPMs
@@ -174,10 +182,26 @@
## openSUSE Development
-The package is automatically submitted from the `master` branch to
-[system:install:head](https://build.opensuse.org/package/show/system:install:head/mkdud)
-OBS project. From that place it is forwarded to
-[openSUSE Factory](https://build.opensuse.org/project/show/openSUSE:Factory).
+To build, simply run `make`. Install with `make install`.
+
+Basically every new commit into the master branch of the repository will be auto-submitted
+to all current SUSE products. No further action is needed except accepting the pull request.
+
+Submissions are managed by a SUSE internal [jenkins](https://jenkins.io) node in the InstallTools tab.
+
+Each time a new commit is integrated into the master branch of the repository,
+a new submit request is created to the openSUSE Build Service. The devel project
+is [system:install:head](https://build.opensuse.org/package/show/system:install….
+
+`*.changes` and version numbers are auto-generated from git commits, you don't have to worry about this.
+
+The spec file is maintained in the Build Service only. If you need to change it for the `master` branch,
+submit to the
+[devel project](https://build.opensuse.org/package/show/system:install:head/mkdud)
+in the build service directly.
+
+Development happens exclusively in the `master` branch. The branch is used for all current products.
-You can find more information about this workflow in the [linuxrc-devtools
+You can find more information about the changes auto-generation and the
+tools used for jenkis submissions in the [linuxrc-devtools
documentation](https://github.com/openSUSE/linuxrc-devtools#opensuse-develo….
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mkdud-1.32/VERSION new/mkdud-1.34/VERSION
--- old/mkdud-1.32/VERSION 2018-04-10 10:20:24.000000000 +0200
+++ new/mkdud-1.34/VERSION 2018-04-26 16:23:20.000000000 +0200
@@ -1 +1 @@
-1.32
+1.34
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mkdud-1.32/changelog new/mkdud-1.34/changelog
--- old/mkdud-1.32/changelog 2018-04-10 10:20:24.000000000 +0200
+++ new/mkdud-1.34/changelog 2018-04-26 16:23:20.000000000 +0200
@@ -1,46 +1,55 @@
-2018-04-06: 1.32
- - merge pr gh#openSUSE/mkdud#12
- - adjust mkdud to work around a problem when updating coreutils (bsc #1087901)
+2018-04-26: 1.34
+ - merge gh#openSUSE/mkdud#14
+ - fix Makefile and update git2log script
+
+2018-04-26: 1.33
+ - merge gh#openSUSE/mkdud#13
+ - improve documentation
+
+2018-04-10: 1.32
+ - merge gh#openSUSE/mkdud#12
+ - adjust mkdud to work around a problem when updating coreutils
+ (bsc#1087901)
2018-03-21: 1.31
- - merge pr gh#openSUSE/mkdud#11
- - adjust CaaSP support (bsc #1085261)
+ - merge gh#openSUSE/mkdud#11
+ - adjust CaaSP support (bsc#1085261)
-2017-05-05: 1.30
- - merge pr gh#openSUSE/mkdud#10
- - fix service pack condition check
+2017-05-08: 1.30
+ - merge gh#openSUSE/mkdud#10
- support openSUSE Kubic
+ - fix service pack condition check
2017-01-13: 1.29
- - merge pr gh#openSUSE/mkdud#9
+ - merge gh#openSUSE/mkdud#9
- follow casp -> caasp renaming
2016-12-14: 1.28
- - merge pr gh#openSUSE/mkdud#8
- - use latest git2log script from linuxrc-devtools package
+ - merge gh#openSUSE/mkdud#8
- support CASP and extend documentation for --dist option
+ - use latest git2log script from linuxrc-devtools package
2016-11-30: 1.27
- - merge pr gh#openSUSE/mkdud#7
- - more readable variable names
- - be more specific about dists that support DUDs as rpm
- - squash dashes ('-') to match more dist name spellings
- - support creating a dud in rpm format (bsc #1006175)
- - adjust documentation to include rpm format
+ - merge gh#openSUSE/mkdud#7
- accept driver updates packed as rpm
+ - adjust documentation to include rpm format
+ - support creating a dud in rpm format (bsc#1006175)
+ - squash dashes ('-') to match more dist name spellings
+ - be more specific about dists that support DUDs as rpm
+ - more readable variable names
2016-11-28: 1.26
- - merge pr gh#openSUSE/mkdud#6
- - even more more verbose message
+ - merge gh#openSUSE/mkdud#6
+ - allow to skip distribution check using --force (bsc#1012241)
- even more verbose error message
- - allow to skip distribution check using --force (bsc #1012241)
+ - even more more verbose message
-2016-02-11: 1.25
- - merge pr gh#openSUSE/mkdud#5
+2016-02-12: 1.25
+ - merge gh#openSUSE/mkdud#5
- add support for leap and tumbleweed
-2016-01-20: 1.24
- - merge pr gh#openSUSE/mkdud#4
+2016-01-21: 1.24
+ - merge gh#openSUSE/mkdud#4
- Remove warning on yast replacement for versions supporting it.
2016-01-19: 1.23
@@ -50,19 +59,20 @@
- added --obs-keys option to retrieve necessary obs project keys
2016-01-13: 1.21
- - use mkpath instead of make_path to be compatible with older perl versions
+ - use mkpath instead of make_path to be compatible with older perl
+ versions
2016-01-13: 1.20
- suppport adding public pgp keys for rpm verification
-2015-09-28: 1.19
- - merge pr gh#openSUSE/mkdud#3
- - Add information about openSUSE development
+2015-09-29: 1.19
+ - merge gh#openSUSE/mkdud#3
- Convert README to Markdown
+ - Add information about openSUSE development
2015-04-30: 1.18
- - clarify iso usage in README
- support creating duds in iso9660 format
+ - clarify iso usage in README
2015-03-04: 1.17
- adjust permissions of gpg dir
@@ -82,8 +92,8 @@
2015-01-26: 1.12
- updated git2log script
-2015-01-20: 1.11
- - merge pr gh#openSUSE/mkdud#1
+2015-01-21: 1.11
+ - merge gh#openSUSE/mkdud#1
- Fix typo
2014-10-13: 1.10
@@ -100,37 +110,37 @@
- add 'format' option to support different DUD formats
2014-01-31: 1.6
- - fixed file magic usage
- - add install make target
- - update docs and up version
- support conditional DUDs
+ - update docs and up version
+ - fixed file magic usage add install make target
2013-11-15: 1.4
- support Ruby files
- better parsing of file locations in ycp/rb files
2013-09-06: 1.3
- - up version
+ - map dist specs like sles11-sp1 to sles11
+ - add --no-docs option: remove package docs (map pages, info pages,
+ /usr/share/doc)
- prevent /usr/src/packages to be created
- new option --force replaces old --may-replace-yast
- clarified dist names for service packs
- - add --no-docs option: remove package docs (map pages, info pages, /usr/share/doc)
- - map dist specs like sles11-sp1 to sles11
+ - up version
2013-08-06: 1.2
- - fix creating some minmalistic driver updates
- - fix documentation
- - update help text
- - corrected version
- - completely rewritten code
- - xxx
- - rename rpm2dud to mkdud
- fix rpm handling
+ - rename rpm2dud to mkdud
+ - xxx
+ - completely rewritten code
+ - corrected version
+ - update help text
+ - fix documentation
+ - fix creating some minmalistic driver updates
2013-03-12: 1.0
- support adding and running ordinary files
2011-09-02: 0.9
- - more make targets
- added Makefile
+ - more make targets
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mkdud-1.32/git2log new/mkdud-1.34/git2log
--- old/mkdud-1.32/git2log 2018-04-10 10:20:24.000000000 +0200
+++ new/mkdud-1.34/git2log 2018-04-26 16:23:20.000000000 +0200
@@ -2,14 +2,13 @@
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#
-# This script is maintained at https://github.com/openSUSE/ssob
+# This script is maintained at https://github.com/openSUSE/linuxrc-devtools
#
# If you're in another project, this is just a copy.
# You may update it to the latest version from time to time...
#
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
use strict;
use Getopt::Long;
@@ -20,297 +19,927 @@
$Data::Dumper::Indent = 1;
sub usage;
-sub get_branch_tags;
-sub get_branch;
-sub get_parent_branch;
+sub changelog_outdated;
+sub get_github_project;
sub get_version;
+sub get_tags;
+sub get_log;
+sub is_formatted_tag;
+sub get_branch;
+sub choose_tags;
+sub add_head_tag;
+sub tags_to_str;
+sub format_log;
+sub format_all_logs;
+sub fix_dates;
+sub add_line_breaks;
+sub format_date_obs;
+sub format_date_iso;
+sub raw_date_to_s;
usage 0 if !@ARGV;
-my @deps = qw ( .git/HEAD .git/refs/heads .git/refs/tags );
+my @changelog_deps = qw ( .git/HEAD .git/refs/heads .git/refs/tags );
my $branch;
my $current_version;
-my $github_project;
my @tags;
my @all_tags;
+my $config;
my $opt_log;
my $opt_version;
my $opt_branch;
my $opt_update;
my $opt_file;
+my $opt_start;
+my $opt_max;
+my $opt_width = 66;
+my $opt_width_fuzz = 8;
+my $opt_sep_width = 68;
+my $opt_format = 'internal'; # obs, internal
+my $opt_merge_msg_before = 1; # log auto generated pr merge message before the commit messages (vs. after)
+my $opt_join_author = 1; # join consecutive commit messages as long as they are by the same author
+my $opt_keep_date = 1; # don't join consecutive commit messages if they have different time stamps
+my $opt_default_email = 'opensuse-packaging(a)opensuse.org'; # default email to use in changelog
GetOptions(
'help' => sub { usage 0 },
'version' => \$opt_version,
'branch' => \$opt_branch,
'update' => \$opt_update,
+ 'start=s' => \$opt_start,
+ 'format=s' => \$opt_format,
+ 'max=i' => \$opt_max,
+ 'width=i' => \$opt_width,
+ 'fuzz=i' => \$opt_width_fuzz,
+ 'merge-msg=s' => sub { $opt_merge_msg_before = ($_[1] eq 'after' ? 0 : 1) },
+ 'join-author!' => \$opt_join_author,
+ 'keep-date!' => \$opt_keep_date,
'log|changelog' => \$opt_log,
+ 'default-email=s' => \$opt_default_email,
) || usage 1;
+# ensure we are used correctly
usage 1 if @ARGV > 1 || !($opt_log || $opt_version || $opt_branch);
$opt_file = @ARGV ? shift : '-';
die "no git repo\n" unless -d ".git";
-if($opt_update && $opt_file ne '-' && -f($opt_file)) {
- my $ok = 1;
+# if update option has been give write changelog only if git refs are newer
+exit 0 if $opt_update && $opt_file ne '-' && -f($opt_file) && !changelog_outdated($opt_file);
+
+$opt_max = 2 if $opt_version || $opt_branch;
+
+# gather some data
+get_github_project;
+get_branch;
+get_log;
+fix_dates;
+get_tags;
+choose_tags;
+add_head_tag;
+get_version;
+
+# just print current branch
+if($opt_branch) {
+ open my $f, ">$opt_file";
+ print $f $config->{branch} ? $config->{branch} : "master", "\n";
+ close $f;
+
+ exit 0;
+}
- my $t = (stat $opt_file)[9];
+# just print current version
+if($opt_version) {
+ my $old_version;
- for (@deps) {
- $ok = 0 if (stat)[9] > $t;
+ if($opt_file ne '-' && open(my $f, $opt_file)) {
+ chomp($old_version = <$f>);
+ close $f;
}
- exit 0 if $ok;
+ if($config->{version} ne $old_version) {
+ open my $f, ">$opt_file";
+ print $f "$config->{version}\n";
+ close $f;
+ }
+
+ exit 0;
}
-if(`git config remote.origin.url` =~ m#github.com[:/]+(\S+/\S+)#) {
- $github_project = $1;
+# set start tag
+if($opt_start) {
+ my $x = is_formatted_tag $opt_start;
+ die "$opt_start: not a valid start tag\n" if !$x;
+ $x->{branch} = $config->{branch} if !$x->{branch};
+ $config->{start} = $x;
}
-@all_tags = `git tag`;
-chomp @all_tags;
+format_all_logs;
-$branch = get_branch;
-die "no branch?\n" unless $branch;
+open my $f, ">$opt_file";
-@tags = get_branch_tags;
-die "no tags at all?\n" unless @tags;
+print $f $_->{formatted} for @{$config->{log}};
-if($branch ne 'master') {
- if(!grep { /^$branch\-/ } @tags) {
- $branch = get_parent_branch;
- die "sorry, can't determine branch\n" unless $branch;
+close $f;
- @tags = get_branch_tags;
- die "no tags at all?\n" unless @tags;
- }
-}
-else {
- @tags = get_branch_tags;
- die "no tags at all?\n" unless @tags;
-}
+exit 0;
-if($opt_branch) {
- open my $f, ">$opt_file";
- print $f "$branch\n";
- close $f;
- exit 0;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# usage(exit_code)
+#
+# Print help message and exit.
+# - exit_code: exit code
+#
+# Function does not return.
+#
+sub usage
+{
+ my $err = shift;
+
+ print <<" usage";
+Usage: git2log [OPTIONS] [FILE]
+Create changelog and project version from git repo.
+ --changelog Write changelog to FILE.
+ --version Write version number to FILE.
+ --branch Write current branch to FILE.
+ --start START_TAG Start with tag START_TAG.
+ --max N Write at most MAX long entries.
+ --update Write changelog or version only if FILE is outdated.
+ --format FORMAT Write log using FORMAT. Supported FORMATs are 'internal' (default) and 'obs'.
+ --width WIDTH Reformat log entries to be max WIDTH chars wide.
+ --fuzz FUZZ Allow log lines to be up to FUZZ chars longer as WIDTH to avoid
+ line breaks leaving tiny bits on the last line.
+ --merge-msg WHERE Log message about merges before or after the actual merge commit messages.
+ Valid values for WHERE are 'after' and 'before' (default).
+ --join-author Join consecutive commits as long as they are by the same author. (default)
+ --no-join-author Keep consecutive commits by the same author separate.
+ --keep-date Join consecutive commits only if they have the same date. (default)
+ --no-keep-date Join consecutive commits even if dates differ.
+ --default-email Use this email in changelog entries if no other suitable email could be
+ determined (default: opensuse-packaging\(a)opensuse.org)
+ --help Print this help text.
+ usage
+
+ exit $err;
}
-$current_version = get_version;
-if($opt_version) {
- open my $f, ">$opt_file";
- print $f "$current_version\n";
- close $f;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# res = changelog_outdated(file)
+#
+# Return status of changelog file.
+# - file: changelog file name
+# - res: status
+# 1: file is newer than the last git repo change and should be updated
+# 0: file is still recent enough
+#
+# Relies on global var @changelog_deps.
+#
+sub changelog_outdated
+{
+ my $file = $_[0];
- exit 0;
+ my $changelog_time = (stat $file)[9];
+
+ return 1 if !defined $changelog_time;
+
+ for (@changelog_deps) {
+ return 1 if (stat)[9] > $changelog_time;
+ }
+
+ return 0;
}
-if($branch ne 'master') {
- my ($i1, $i2, $bi);
- for (my $i = 0; $i < @tags; $i++) {
- if($tags[$i] =~ /^$branch\-(\S+)/) {
- $i2 = $i;
- $bi = $1;
- last;
- }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_github_project()
+#
+# Set $config->{github_project} to the github project name.
+#
+sub get_github_project
+{
+ if(`git config remote.origin.url` =~ m#github.com[:/]+(\S+/\S+)#) {
+ $config->{github_project} = $1;
+ $config->{github_project} =~ s/\.git$//;
}
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_version()
+#
+# Set $config->{branch} and $config->{version} to the current branch and
+# version info.
+#
+# This might be taken directly from HEAD if HEAD is tagged or otherwise be
+# exprapolated from the most recent tag (cf. add_head_tag()).
+#
+sub get_version
+{
+ $config->{version} = "0.0";
+
+ my $tag = $config->{log}[0]{tags}[0];
+
+ if($tag->{version}) {
+ $config->{version} = $tag->{version};
+ $config->{branch} = $tag->{branch};
+ }
+}
+
- # print STDERR ">> $branch-$bi\n";
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_tags()
+#
+# Parse $config->{raw_log}, extract tag names, and split into per-tag
+# sections.
+#
+# Only tags recognized by is_formatted_tag() are considered.
+#
+# The parsed logs is stored in $config->{log}, an array of log sections.
+# Each section is a hash with these keys:
+# - 'tags': array of tags for this section
+# - 'commit': git commit id associated with these tags
+# - 'lines': git log lines
+#
+sub get_tags
+{
+ my $log_entry;
- warn "no tags in this branch yet\n" unless $bi;
+ for (@{$config->{raw_log}}) {
+ if(/^commit (\S+)( \((.*)\))?/) {
+ my $commit = $1;
+ my $tag_list = $3;
+ my $xtag;
+
+ for my $t (split /, /, $tag_list) {
+ if($t =~ /tag: (\S+)/) {
+ my $tag = $1;
+ my $x = is_formatted_tag $tag;
+ push @$xtag, $x if $x;
+ }
+ }
- for (my $i = 0; $i < $i2; $i++) {
- if($tags[$i] ge $bi) {
- if($tags[$i] eq $bi) {
- $i1 = $i;
+ if($xtag) {
+ if($log_entry) {
+ push @{$config->{log}}, $log_entry;
+ last if $opt_max && @{$config->{log}} >= $opt_max;
+ }
+ $log_entry = { commit => $commit, tags => $xtag };
}
- elsif($i > 0) {
- $i1 = $i - 1;
+ else {
+ $log_entry = { commit => $commit } if !$log_entry;
}
- last;
}
+
+ push @{$log_entry->{lines}}, $_ if $log_entry;
}
+}
- splice @tags, $i1, $i2 - $i1;
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_log()
+#
+# Read git log and store lines as array in $config->{raw_log} (trailing
+# newlines removed).
+#
+sub get_log
+{
+ chomp(@{$config->{raw_log}} = `git log --pretty=medium --date=raw --topo-order --decorate`);
}
-map { s/(\d+)/$1 + 0/eg } @tags;
-push @tags, "HEAD";
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# hash_ref = is_formatted_tag(tag_name)
+#
+# Parse tag and return hash ref with branch and version number parts or
+# undef if it doesn't match.
+# - tag_name: tag as string
+# - hash_ref: hash ref with internal tag representation (with keys 'branch' and 'version').
+#
+# This expects tags of the form "VERSION" or "BRANCH-VERSION" where VERSION
+# consists of decimal numbers separated by dots '.' and BRANCH can be any
+# string.
+# (Note: it doesn't really have to be the name of an existing branch.)
+#
+# Tags not conforming to this convention are ignored.
+#
+sub is_formatted_tag
+{
+ if($_[0] =~ /^((.+)-)?((\d+\.)*\d+)$/) {
+ return { branch => $2, version => $3 }
+ }
-# print Dumper(\@tags);
+ return undef;
+}
-open F, ">$opt_file";
-for (my $i = @tags - 1; $i > 0; $i--) {
- my ($date, @t2);
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_branch()
+#
+# Get currently active git branch and store in $config->{branch}.
+#
+# 'master' branch is represented by empty 'branch' key.
+#
+sub get_branch
+{
+ chomp(my $branch = `git rev-parse --abbrev-ref HEAD`);
- my @t = `git log --pretty=medium --date=iso '$tags[$i-1]..$tags[$i]'`;
+ $branch = "" if $branch eq 'master';
- # print "\n--- $tags[$i-1]..$tags[$i] ---\n", @t, "---\n";
+ $config->{branch} = $branch;
+}
- my $merge = 0;
- for (@t) {
- $merge = 1 if /^Merge: /;
- $merge = 0 if /^commit /;
- push @t2, $_ if !$merge;
- if(/^ Merge pull request #(\d+) from /) {
- push @t2, "merge pr gh#$github_project#$1\n" if $github_project;
- }
- }
- @t = @t2;
- undef @t2;
- my $detail = 0;
- for (@t) {
- $detail = 1 if /^ $/;
- $detail = 2 if /^ Conflicts:$/;
- $detail = 0 if /^commit /;
- if(!$detail) {
- push @t2, $_ if $detail < 2;
- }
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# res = tag_sort(a, b)
+#
+# Compare 2 tags.
+# - a, b: refs to tag hash
+# - res: -1, 0, 1
+#
+# This is used when we have to decide between alternative tags.
+# (Prefer 'lesser' variant.)
+#
+sub tag_sort
+{
+ my ($x, $y);
+
+ $x = length $a->{version};
+ $y = length $b->{version};
+
+ # longer version number first
+ return $y <=> $x if $y <=> $x;
+
+ return $a->{branch} cmp $b->{branch};
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# str = tag_to_str(tag_ref)
+#
+# Convert tag into string.
+# - tag_ref: ref to hash with 'branch' and 'version' keys
+# - str: string (e.g. "foo-1.44")
+#
+# 'master' branch is represented by missing/empty 'branch' key.
+#
+sub tag_to_str
+{
+ my $tag = $_[0];
+ my $str;
+
+ $str = "$tag->{branch}-" if $tag->{branch} ne "";
+ $str .= $tag->{version};
+
+ return $str;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# str = tags_to_str(tag_array_ref)
+#
+# Convert array of tags into string.
+# - tag_array_ref: ref to array of tags
+# - str: string (e.g. "(tag1, tag2)"
+#
+# This function is used only internally for debugging.
+#
+sub tags_to_str
+{
+ my $tags = $_[0];
+ my $str;
+
+ for my $t (@$tags) {
+ $str .= ", " if $str;
+ $str .= tag_to_str $t;
}
- @t = @t2;
- # print "\n--- $tags[$i-1]..$tags[$i] ---\n", @t;
+ return "($str)";
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# choose_tags()
+#
+# Scan commit messages and extract tag & branch information.
+#
+# This stores the tag/branch info in $config->{log}[]{tags}.
+#
+sub choose_tags
+{
+ my $branch = $config->{branch};
+
+ for my $x (@{$config->{log}}) {
+ # printf "# %s\n", tags_to_str($x->{tags});
+
+ # no tag info? -> ignore
+ next if !$x->{tags};
- chomp @t;
- for (@t) {
- if(/^Date:\s*(\S+)/) {
- $date = $1;
- last;
+ # single tag? -> remember branch info
+ if(@{$x->{tags}} == 1) {
+ $branch = $x->{tags}[0]{branch};
+ next;
}
- }
- # handle white space in every first line once and for all
- my $empty = 1;
- for (@t) {
- $empty = 1, $_ = "", next if $_ =~ /^\s*$/;
- next if !$empty;
- s/^\s*//;
- $empty = 0;
- }
+ # several tags? -> choose one
+
+ # any with current branch name?
+ my @t = grep { $_->{branch} eq $branch } @{$x->{tags}};
- @t = grep { !/^(commit|Author:|Date:|Merge:|\s*$)|created.*tag/ } @t;
- if(@t) {
- # rewrite a bit to have it look more consistent
- map { s/(fate|bnc|bsc)#/$1 #/g } @t;
- map { s/(fate|bnc|bsc)\s*(\d{4})/$1 #$2/g } @t;
- map { s/\(#/(bnc #/g } @t;
- map { s/bug\s*#/bnc #/g } @t;
- map { s/feat(\.|ure)?\s*#?(\d+)/fate #$2/g } @t;
- map { s/^ {4}// } @t;
- map { s/^ {8}// } @t;
- map { s/^ +/ / } @t;
- map { s/^\s*[+\-][\-\s]*/- / } @t;
- map { s/^([^ \-])/- $1/ } @t;
- map { s/^/\t/ } @t;
- map { s/\\'/'/ } @t;
+ # no? -> choose among all
+ @t = @{$x->{tags}} if @t == 0;
- # print "\n--- $tags[$i-1]..$tags[$i] ---\n", join("\n", @t);
+ # prefer longest version number, then alphanumerically smallest branch name
+ @t = sort tag_sort @t;
- my $t = $tags[$i];
- $t = "${branch}-$t" if $branch ne 'master' && $t eq "HEAD";
- $t =~ s/HEAD/$current_version/;
- print F "$date:\t$t\n";
- print F join("\n", @t), "\n\n";
+ $branch = $t[0]{branch};
+ $x->{tags} = [ $t[0] ];
+
+ # printf "X %s\n", tags_to_str($x->{tags});
}
}
-close F;
-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-sub usage
+# add_head_tag()
+#
+# Suggest tag for HEAD if there isn't one.
+#
+# Basically, use branch + version from most recent tag and increment version.
+#
+sub add_head_tag
{
- my $err = shift;
+ return if @{$config->{log}} < 2;
- print <<" usage";
-Usage: git2log [OPTIONS] [FILE]
-Create changelog and project version from git repo.
- --changelog Write changelog to FILE.
- --version Write version number to FILE.
- --branch Write current branch to FILE.
- --update Write changelog or version only if FILE is outdated.
- --help Print this help text.
- usage
+ # HEAD tagged already?
+ return if $config->{log}[0]{tags};
- exit $err;
+ # the first tagged commit if HEAD isn't tagged
+ my $tag = { %{$config->{log}[1]{tags}[0]} };
+
+ # increment version
+ $tag->{version} =~ s/(\d+)$/$1 + 1/e;
+
+ $config->{log}[0]{tags}[0] = $tag;
+
+ # remember that the tag was generated
+ $config->{log}[0]{was_untagged} = 1;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-sub get_branch_tags
+# fix_dates()
+#
+# Adjust time stamps in entire git log.
+#
+# The time stamps of the git commits are not necessarily ordered by date.
+# But the generated changelog is required to have a strictly monotonic time.
+#
+# We do this by going through the log in reverse and rewriting any dates we
+# find whenever the date decreases.
+#
+# A minimum time difference of 1 second beween entries is maintained.
+#
+# Not very subtle but it works.
+#
+sub fix_dates
{
- my @ntags;
+ my $last_date;
+
+ for (reverse @{$config->{raw_log}}) {
+ # e.g. "Date: 1443184889 +0200"
+ if(/^(Date:\s+)(\S+)(\s+\S+)/) {
+ if(defined $last_date && $2 < $last_date) {
+ $_ = "$1$last_date$3\n";
+ }
+ else {
+ $last_date = $2;
+ }
- for (@all_tags) {
- if(/^\d/) {
- s/(\d+)/sprintf "%04d", $1/eg;
- push @ntags, $_;
+ # ensure a minimal time gap of 1 second
+ $last_date += 1;
}
- elsif(s/^$branch\-//) {
- s/(\d+)/sprintf "%04d", $1/eg;
- push @ntags, "$branch-$_";
+ }
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# format_all_logs()
+#
+# Format the entire git log.
+#
+# This is done for every code version individually (the log has already been
+# split accordingly).
+#
+# If $config->{start} is set, use this as starting point. Else format the
+# entire git log.
+#
+sub format_all_logs
+{
+ # check if start tag actually exists - if not, print nothing
+ if($config->{start}) {
+ my $tag_found;
+ for (@{$config->{log}}) {
+ $tag_found = 1, last if grep { tag_to_str($config->{start}) eq tag_to_str($_) } @{$_->{tags}};
}
+ return if !$tag_found;
}
- return sort @ntags;
+ for (@{$config->{log}}) {
+ if($config->{start}) {
+ # stop if we meet the start tag
+ last if grep { tag_to_str($config->{start}) eq tag_to_str($_) } @{$_->{tags}};
+ }
+ format_log $_;
+ }
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-sub get_branch
+# format_log(log)
+#
+# Format log messages.
+# - log: is an array ref with individual commits
+#
+# All commits belong to a specific code version (stored in $log->{tag}).
+# $log->{formatted} holds the result.
+#
+# The process is done in several individual steps, documented below in the code.
+#
+sub format_log
{
- my $b;
+ my $log = $_[0];
+
+ my $merge;
+ my $commit;
+ my $saved_commit;
+ my $commits;
+
+ for (@{$log->{lines}}) {
+ if(/^commit (\S+)/) {
+ $commit = { ref => $1 };
+ push @{$commits}, $commit;
+
+ if(
+ $merge &&
+ $merge->{merge_end} eq substr($commit->{ref}, 0, length($merge->{merge_end}))
+ ) {
+ undef $merge;
+ }
+
+ if($merge) {
+ $commit->{merge_ref} = $merge->{ref};
+ $commit->{date} = $merge->{date};
+ # add to all commits so it's not lost when we re-arrange
+ $commit->{merge_msg} = $merge->{msg} if $merge->{msg};
+ # saved entry no longer needed
+ undef $saved_commit;
+ }
+
+ next;
+ }
+
+ if(/^Merge: (\S+)/) {
+ if($commit) {
+ $merge = { merge_end => $1, ref => $commit->{ref} } unless $merge;
+ $saved_commit = pop @{$commits};
+ }
+ undef $commit;
+ next;
+ }
+
+ if(/^Date:\s+(\S.*)/) {
+ if($commit) {
+ $commit->{date} = $1 if !$commit->{date};
+ }
+ elsif($merge) {
+ $merge->{date} = $1 if !$merge->{date};
+ }
+ next;
+ }
+
+ if(/^Author:\s+(\S.*)/) {
+ $commit->{author} = $1 if $commit;
+ $merge->{author} = $1 if $merge && !$merge->{author};
+ next;
+ }
+
+ if($commit) {
+ push @{$commit->{lines}}, $_ if s/^ //;
+ }
+ elsif($merge && !$merge->{msg}) {
+ if(/^ Merge pull request (#\d+) from (\S+)/) {
+ if($config->{github_project}) {
+ $merge->{msg} = "merge gh#$config->{github_project}$1";
+ }
+ else {
+ $merge->{msg} = "merge pr $2";
+ }
+ }
+ elsif(/^ Merge branch '([^']+)'/) {
+ $merge->{msg} = "merge branch $1";
+ }
+ }
+ }
+
+ # it can happen that there's a lonely merge commit left at the end
+ if($merge && $saved_commit) {
+ $saved_commit->{merge_ref} = $merge->{ref};
+ $saved_commit->{date} = $merge->{date};
+ $saved_commit->{author} = $merge->{author};
+ $saved_commit->{merge_msg} = $merge->{msg} if $merge->{msg};
+ $saved_commit->{formatted} = [];
+
+ push @{$commits}, $saved_commit;
+ }
+
+ # Note: the individual steps below work on the array @$commits and modify
+ # its content.
+
+ # step 1
+ # - if there are paragraphs starting with '@log@' or '@+log@'
+ # - delete first paragraph (short summary)
+ # - else
+ # - keep only first paragraph
+ # - if there is a paragraph starting with '@-log', delete entire log
+ # - tag commits that have a '@log@' tag so we can delete untagged commits
+ # belonging to the same merge commit later
+
+ my $tagged_merges = {};
+
+ for my $commit (@$commits) {
+ my $para_cnt = 0;
+ my $delete_all = 0;
+ my $delete_first = 0;
+ for (@{$commit->{lines}}) {
+ $para_cnt++ if $_ eq "";
+ $para_cnt = 0, $delete_first = 1 if /^\@\+log\@/;
+ $delete_all = 1 if /^\@\-log\@/;
+ if(/^\@log\@/) {
+ $para_cnt = 0;
+ $commit->{clear} = 1;
+ $tagged_merges->{$commit->{merge_ref}} = 1 if $commit->{merge_ref} || $log->{was_untagged};
+ }
+ $_ = undef if $para_cnt;
+ }
+ shift @{$commit->{lines}} if $delete_first;
+ $commit->{lines} = [] if $delete_all;
+ }
- for (`git branch`) {
- if(/^\*\s+(\S+)/) {
- $b = $1;
- last;
+ # step 2
+ # - clean up tagged commits or commits belonging to tagged merges
+
+ for my $commit (@$commits) {
+ next unless $commit->{clear} || $tagged_merges->{$commit->{merge_ref}};
+ for (@{$commit->{lines}}) {
+ last if /^\@\+?log\@/;
+ $_ = undef;
+ }
+ }
+
+ # step 3
+ # - join lines
+
+ for my $commit (@$commits) {
+ my $lines;
+ my $line;
+
+ for (@{$commit->{lines}}) {
+ next if $_ eq "";
+ if(
+ s/^\s*[+\-][\-\s]*// ||
+ s/^\@\+?log\@// ||
+ $line eq ""
+ ) {
+ s/^\s*//;
+ push @$lines, $line if $line ne "";
+ $line = $_;
+ }
+ else {
+ s/^\s*//;
+ $line .= " " if $line ne "";
+ $line .= $_;
+ }
+ }
+ push @$lines, $line if $line ne "";
+
+ $commit->{formatted} = $lines if $lines;
+ }
+
+ # step 4
+ # - fix small glitches
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted};
+ for (@{$commit->{formatted}}) {
+ s/(fate|bnc|bsc)\s*(#\d+)/\L$1\E$2/ig;
}
}
- $b = "master" if $b eq '(no';
+ # step 5
+ # - add merge info at the top or bottom (depending on $opt_merge_msg_before)
+
+ my $merge_logged;
+
+ for my $commit ($opt_merge_msg_before ? reverse(@$commits) : @$commits) {
+ next unless $commit->{formatted};
+
+ if($commit->{merge_ref} && !$merge_logged->{$commit->{merge_ref}}) {
+ $merge_logged->{$commit->{merge_ref}} = 1;
+ if($commit->{merge_msg}) {
+ if($opt_merge_msg_before) {
+ unshift @{$commit->{formatted}}, $commit->{merge_msg};
+ }
+ else {
+ push @{$commit->{formatted}}, $commit->{merge_msg};
+ }
+ }
+ }
+ }
+
+ # step 6
+ # - join commit messages with same author (optionally even with different dates)
+
+ my $commit0;
+
+ for my $commit (@$commits) {
+ next if !$commit->{formatted};
+ $commit0 = $commit, next if !$commit0;
+
+ if(
+ # $commit->{merge_ref} eq $commit0->{merge_ref} &&
+ (
+ $opt_join_author && ($commit->{author} eq $commit0->{author})
+ && (!$opt_keep_date || $commit->{date} eq $commit0->{date})
+ )
+ || $opt_format eq 'internal'
+ ) {
+ unshift @{$commit0->{formatted}}, @{$commit->{formatted}};
+ delete $commit->{formatted};
+ }
+ else {
+ $commit0 = $commit;
+ }
+ }
+
+ # step 7
+ # - add version tag at the end of the first log entry
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted};
+
+ if($opt_format eq 'obs') {
+ push @{$commit->{formatted}}, $log->{tags}[0]{version} if defined $log->{tags}[0]{version};
+ }
+ else {
+ # push @{$commit->{formatted}}, tag_to_str($log->{tags}[0]);
+ }
+
+ last;
+ }
+
+ # step 8
+ # - add line breaks
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted};
+ for (@{$commit->{formatted}}) {
+ $_ = add_line_breaks $_;
+ }
+ }
- return $b;
+ # step 9
+ # - generate final log message
+ #
+ # note: non-(open)suse email addresses are replaced by $opt_default_email
+
+ my $formated_log;
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted} && @{$commit->{formatted}};
+
+ if($opt_format eq 'obs') {
+ $formated_log .= "-" x $opt_sep_width . "\n";
+ $formated_log .= format_date_obs($commit->{date});
+ }
+ else {
+ $formated_log .= format_date_iso($commit->{date});
+ }
+ if($opt_format eq 'obs') {
+ my $auth = $commit->{author};
+ $auth =~ s/^.*<//;
+ $auth =~ s/>.*$//;
+ # replace non-suse e-mail addresses with a generic one
+ if($auth !~ /\(a)(suse\.(com|cz|de)|opensuse\.org)$/) {
+ $auth = $opt_default_email;
+ }
+ $formated_log .= " - $auth\n\n";
+ }
+ else {
+ $formated_log .= ":\t" . tag_to_str($log->{tags}[0]) . "\n";
+ }
+
+ for (@{$commit->{formatted}}) {
+ s/^/\t/mg if $opt_format eq 'internal';
+ $formated_log .= "$_\n";
+ }
+
+ $formated_log .= "\n";
+ }
+
+ $log->{formatted} = $formated_log;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-sub get_parent_branch
+# new_text = add_line_breaks(text)
+#
+# Add line breaks to text.
+# - text: some text
+# - new_text: same text, reformatted
+#
+# Lines are formatted to have a maximal length of $opt_width. If this causes
+# the last line to be shorter than $opt_width_fuzz, it is appended to the
+# previous line.
+#
+sub add_line_breaks
{
- my $p;
+ my @words = split /\s+/, @_[0];
+ my $remaining_len = length(join '', @words);
- for (`git log -g --pretty=oneline`) {
- $p = $1 if /checkout: moving from (\S+) to $branch/;
- }
+ my $str = shift(@words);
+ my $len = length $str;
+
+ my $next_len;
+ my $word_len;
- # print "parent = $p\n";
+ for (@words) {
+ $word_len = length;
+ $remaining_len -= $word_len;
+ $next_len = $len + $word_len + 1;
+ if(
+ $next_len >= $opt_width &&
+ $next_len + $remaining_len + 1 >= $opt_width + $opt_width_fuzz
+ ) {
+ $str .= "\n $_";
+ $len = $word_len;
+ }
+ else {
+ $str .= " $_";
+ $len += $word_len + 1;
+ }
+ }
- return $p || "master";
+ return "- " . $str;
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-sub get_version
+# seconds = raw_date_to_s(git_date)
+#
+# Convert git raw date to seconds.
+# - git_date: raw git format (e.g. "1443184889 +0200")
+# - seconds: the seconds part (e.g. "1443184889")
+#
+sub raw_date_to_s
{
- my $v = $tags[-1];
- $v =~ s/(\d+)/$1 + 0/eg;
+ return (split / /, $_[0])[0];
+}
- if(`git log --pretty=medium --date=iso '$v..HEAD'`) {
- $v =~ s/(\d+)$/$1 + 1/e;
- }
- $v =~ s/^$branch\-//;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# date = format_date_obs(git_date)
+#
+# Convert git raw date to obs format.
+# - git_date: raw git format (e.g. "1443184889 +0200")
+# - date: obs format ("Fri Sep 25 12:41:29 UTC 2015")
+#
+sub format_date_obs
+{
+ my @d = gmtime(raw_date_to_s($_[0]));
- return $v;
+ return
+ qw(Sun Mon Tue Wed Thu Fri Sat)[$d[6]] . " " .
+ qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[$d[4]] . " " .
+ $d[3] . " " .
+ sprintf("%02d:%02d:%02d", $d[2], $d[1], $d[0]) . " UTC " .
+ (1900 + $d[5]);
}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# date = format_date_iso(git_date)
+#
+# Convert git raw date to iso format.
+# - git_date: raw git format (e.g. "1443184889 +0200")
+# - date: obs format ("2015-09-25")
+#
+sub format_date_iso
+{
+ my @d = gmtime(raw_date_to_s($_[0]));
+
+ return sprintf("%04d-%02d-%02d", 1900 + $d[5], $d[4] + 1, $d[3]);
+}
1
0
Hello community,
here is the log from the commit of package python-bpython for openSUSE:Factory checked in at 2018-04-27 16:09:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-bpython (Old)
and /work/SRC/openSUSE:Factory/.python-bpython.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-bpython"
Fri Apr 27 16:09:08 2018 rev:2 rq:601613 version:0.17
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-bpython/python-bpython.changes 2017-09-13 22:36:52.948302175 +0200
+++ /work/SRC/openSUSE:Factory/.python-bpython.new/python-bpython.changes 2018-04-27 16:09:13.526503980 +0200
@@ -1,0 +2,19 @@
+Thu Apr 26 13:58:01 UTC 2018 - badshah400(a)gmail.com
+
+- Update to version 0.17:
+ * New features:
+ - gh#bpython/bpython#641: Implement Ctrl+O.
+ - Add default_autoreload config option.
+ * Fixes:
+ - Fix deprecation warnings.
+ - Do not call signal outside of main thread.
+ - Fix option-backspace behavior.
+ - gh#bpython/bpython#648: Fix paste helper.
+ - gh#bpython/bpython#653: Handle docstrings more carefully.
+ - gh#bpython/bpython#654: Do not modify history file during
+ tests.
+ - gh#bpython/bpython#658: Fix newline handling.
+ - gh#bpython/bpython#670: Fix handlign of ANSI escape codes.
+ - gh#bpython/bpython#687: Fix encoding of jedi completions.
+
+-------------------------------------------------------------------
Old:
----
bpython-0.16.tar.gz
New:
----
bpython-0.17.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-bpython.spec ++++++
--- /var/tmp/diff_new_pack.bot7jy/_old 2018-04-27 16:09:14.734459677 +0200
+++ /var/tmp/diff_new_pack.bot7jy/_new 2018-04-27 16:09:14.738459530 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-bpython
#
-# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -13,17 +13,18 @@
# published by the Open Source Initiative.
# Please submit bugfixes or comments via http://bugs.opensuse.org/
+#
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
%bcond_with test
Name: python-bpython
-Version: 0.16
+Version: 0.17
Release: 0
-License: MIT
Summary: Fancy Interface to the Python Interpreter
-Url: http://www.bpython-interpreter.org/
+License: MIT
Group: Development/Languages/Python
+Url: http://www.bpython-interpreter.org/
Source: https://files.pythonhosted.org/packages/source/b/bpython/bpython-%{version}…
BuildRequires: %{python_module Babel}
BuildRequires: %{python_module Sphinx}
@@ -42,12 +43,12 @@
BuildRequires: %{python_module wcwidth}
BuildRequires: python-mock
%endif
+Requires: %{name}-common = %{version}
Requires: python-curtsies >= 0.1.18
Requires: python-greenlet
Requires: python-pygments
Requires: python-requests
Requires: python-six >= 1.5
-Requires: %{name}-common = %{version}
Recommends: python-pyOpenSSL
Recommends: python-pyasn1
Recommends: python-ndg-httpsclient
@@ -76,6 +77,7 @@
%package -n %{name}-common
Provides: %{python_module bpython-common = %{version}}
Summary: Fancy Interface to the Python Interpreter - common files
+Group: Development/Languages/Python
%description -n %{name}-common
This package contains files shared between the various versions of
@@ -133,7 +135,6 @@
rm %{buildroot}%{_datadir}/appdata/bpython.appdata.xml
rm %{buildroot}%{_datadir}/applications/bpython.desktop
-
%if %{with test}
%check
%python_exec setup.py test
++++++ bpython-0.16.tar.gz -> bpython-0.17.tar.gz ++++++
++++ 2462 lines of diff (skipped)
1
0
Hello community,
here is the log from the commit of package lsyncd for openSUSE:Factory checked in at 2018-04-27 16:09:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lsyncd (Old)
and /work/SRC/openSUSE:Factory/.lsyncd.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "lsyncd"
Fri Apr 27 16:09:01 2018 rev:15 rq:601610 version:2.1.5
Changes:
--------
--- /work/SRC/openSUSE:Factory/lsyncd/lsyncd.changes 2018-02-06 16:49:03.776324455 +0100
+++ /work/SRC/openSUSE:Factory/.lsyncd.new/lsyncd.changes 2018-04-27 16:09:11.330584519 +0200
@@ -1,0 +2,5 @@
+Tue Apr 17 13:48:00 UTC 2018 - mikhail.kasimov(a)gmail.com
+
+- Updated path to lsyncd.conf for lsyncd.service and lsyncd.sysconfig
+(boo#975118)
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ lsyncd.service ++++++
--- /var/tmp/diff_new_pack.cMbShu/_old 2018-04-27 16:09:11.982560607 +0200
+++ /var/tmp/diff_new_pack.cMbShu/_new 2018-04-27 16:09:11.982560607 +0200
@@ -6,7 +6,7 @@
Type=simple
Nice=19
EnvironmentFile=-/etc/sysconfig/lsyncd
-ExecStart=/usr/bin/sh -c 'eval `/usr/bin/lsyncd -nodaemon $LSYNCD_OPTIONS /etc/lsyncd.conf`'
+ExecStart=/usr/bin/sh -c 'eval `/usr/bin/lsyncd -nodaemon $LSYNCD_OPTIONS /etc/lsyncd/lsyncd.conf`'
[Install]
WantedBy=multi-user.target
++++++ lsyncd.sysconfig ++++++
--- /var/tmp/diff_new_pack.cMbShu/_old 2018-04-27 16:09:12.002559873 +0200
+++ /var/tmp/diff_new_pack.cMbShu/_new 2018-04-27 16:09:12.006559727 +0200
@@ -1,6 +1,6 @@
# Keep the space there for systemd. Don't nest variables without
# changing the systemd service file to use: /usr/bin/sh -c 'eval XXXX'
#
-#LSYNCD_OPTIONS="-pidfile /run/lsyncd.pid /etc/lsyncd.conf"
+#LSYNCD_OPTIONS="-pidfile /run/lsyncd.pid /etc/lsyncd/lsyncd.conf"
#LSYNCD_OPTIONS=" "
1
0
Hello community,
here is the log from the commit of package parti for openSUSE:Factory checked in at 2018-04-27 16:09:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/parti (Old)
and /work/SRC/openSUSE:Factory/.parti.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "parti"
Fri Apr 27 16:09:05 2018 rev:7 rq:601612 version:1.18
Changes:
--------
--- /work/SRC/openSUSE:Factory/parti/parti.changes 2018-04-26 13:38:43.738546026 +0200
+++ /work/SRC/openSUSE:Factory/.parti.new/parti.changes 2018-04-27 16:09:12.238551218 +0200
@@ -1,0 +2,9 @@
+Thu Apr 26 14:05:19 UTC 2018 - wfeldt(a)opensuse.org
+
+- merge gh#wfeldt/parti#9
+- improve doc a bit
+- update git2log script to latest version
+- reference obs builds
+- 1.18
+
+--------------------------------------------------------------------
Old:
----
parti-1.17.tar.xz
New:
----
parti-1.18.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ parti.spec ++++++
--- /var/tmp/diff_new_pack.RjlFqh/_old 2018-04-27 16:09:12.738532880 +0200
+++ /var/tmp/diff_new_pack.RjlFqh/_new 2018-04-27 16:09:12.742532733 +0200
@@ -18,7 +18,7 @@
Name: parti
-Version: 1.17
+Version: 1.18
Release: 0
Summary: Show partition table information
License: GPL-3.0
++++++ parti-1.17.tar.xz -> parti-1.18.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.17/README.md new/parti-1.18/README.md
--- old/parti-1.17/README.md 2018-04-25 15:37:55.000000000 +0200
+++ new/parti-1.18/README.md 2018-04-26 16:05:19.000000000 +0200
@@ -22,14 +22,34 @@
So it can be used to verify the data your favorite partitioning tool has
actually written.
+## Downloads
+
+Get the latest version from the [openSUSE Build Service](https://software.opensuse.org/package/parti).
+
## openSUSE Development
-The package is automatically submitted from the `master` branch to
-[system:install:head](https://build.opensuse.org/package/show/system:install:head/parti)
-OBS project. From that place it is forwarded to
-[openSUSE Factory](https://build.opensuse.org/project/show/openSUSE:Factory).
+To build, simply run `make`. Install with `make install`.
+
+Basically every new commit into the master branch of the repository will be auto-submitted
+to all current SUSE products. No further action is needed except accepting the pull request.
+
+Submissions are managed by a SUSE internal [jenkins](https://jenkins.io) node in the InstallTools tab.
+
+Each time a new commit is integrated into the master branch of the repository,
+a new submit request is created to the openSUSE Build Service. The devel project
+is [system:install:head](https://build.opensuse.org/package/show/system:install….
+
+`*.changes` and version numbers are auto-generated from git commits, you don't have to worry about this.
+
+The spec file is maintained in the Build Service only. If you need to change it for the `master` branch,
+submit to the
+[devel project](https://build.opensuse.org/package/show/system:install:head/parti)
+in the build service directly.
+
+Development happens exclusively in the `master` branch. The branch is used for all current products.
-You can find more information about this workflow in the [linuxrc-devtools
+You can find more information about the changes auto-generation and the
+tools used for jenkis submissions in the [linuxrc-devtools
documentation](https://github.com/openSUSE/linuxrc-devtools#opensuse-develo….
## Example
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.17/VERSION new/parti-1.18/VERSION
--- old/parti-1.17/VERSION 2018-04-25 15:37:55.000000000 +0200
+++ new/parti-1.18/VERSION 2018-04-26 16:05:19.000000000 +0200
@@ -1 +1 @@
-1.17
+1.18
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.17/changelog new/parti-1.18/changelog
--- old/parti-1.17/changelog 2018-04-25 15:37:55.000000000 +0200
+++ new/parti-1.18/changelog 2018-04-26 16:05:19.000000000 +0200
@@ -1,41 +1,54 @@
+2018-04-26: 1.18
+ - merge gh#wfeldt/parti#9
+ - improve doc a bit
+ - update git2log script to latest version
+ - reference obs builds
+
2018-04-25: 1.17
+ - merge gh#wfeldt/parti#8
- extended documentation
2018-03-06: 1.16
+ - merge gh#wfeldt/parti#7
- Use standard location for isoinfo binary
-2017-09-08: 1.15
+2017-09-11: 1.15
+ - merge gh#wfeldt/parti#6
- show more details about extended partition links
- - verbose now also shows for every partition where it is referenced (that is
-2017-03-31: 1.14
- - update docs a bit
- - code de-duplication
- - re-arrange fat fs output a bit
+2017-04-03: 1.14
+ - merge gh#wfeldt/parti#4
- parse vfat super block
+ - re-arrange fat fs output a bit
+ - code de-duplication
+ - update docs a bit
-2015-10-12: 1.13
- - show decoded gpt attribute bits
+2016-10-14: 1.13
+ - merge branch master
2016-10-14: 1.12
+ - merge gh#wfeldt/parti#3
+ - show decoded gpt attribute bits
- added some GPT GUIDs of linux partitions
-2015-09-28: 1.11
+2015-10-12: 1.11
+ - merge branch master
+
+2015-10-07: 1.10
+ - merge gh#wfeldt/parti#2
- recognize prep partition type
- also show file system uuid
-
-2015-10-01: 1.10
- - gitignore
- - README: links to explain the information being handled
- - Add link to linux-devtools documentation
- Convert README to Markdown
+ - Add link to linux-devtools documentation
+ - README: links to explain the information being handled
+ - gitignore
2015-07-22: 1.9
- improved zipl parsing
2015-07-17: 1.8
- - support parsing zIPL on scsi devices
- fix endianness issues
+ - support parsing zIPL on scsi devices
2014-10-20: 1.7
- show file name if partition refers to a file
@@ -53,20 +66,20 @@
- show file names in el-torito boot entries
2014-10-16: 1.2
- - added 'archive' Makefile target
- - updated git2log script
- add bios boot partition type
+ - updated git2log script
+ - added 'archive' Makefile target
2013-07-23: 1.1
- - adjusted help text
- - fixed Makefile
- added license and basic docs
+ - fixed Makefile
+ - adjusted help text
2013-07-23: 1.0
- - added log script
- - fix Makefile
- - rename to parti
- - nicer
- - add apple & el torito
- x
+ - add apple & el torito
+ - nicer
+ - rename to parti
+ - fix Makefile
+ - added log script
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/parti-1.17/git2log new/parti-1.18/git2log
--- old/parti-1.17/git2log 2018-04-25 15:37:55.000000000 +0200
+++ new/parti-1.18/git2log 2018-04-26 16:05:19.000000000 +0200
@@ -1,5 +1,16 @@
#! /usr/bin/perl
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#
+# This script is maintained at https://github.com/openSUSE/linuxrc-devtools
+#
+# If you're in another project, this is just a copy.
+# You may update it to the latest version from time to time...
+#
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+use strict;
+
use Getopt::Long;
use Data::Dumper;
@@ -8,198 +19,927 @@
$Data::Dumper::Indent = 1;
sub usage;
+sub changelog_outdated;
+sub get_github_project;
+sub get_version;
+sub get_tags;
+sub get_log;
+sub is_formatted_tag;
+sub get_branch;
+sub choose_tags;
+sub add_head_tag;
+sub tags_to_str;
+sub format_log;
+sub format_all_logs;
+sub fix_dates;
+sub add_line_breaks;
+sub format_date_obs;
+sub format_date_iso;
+sub raw_date_to_s;
usage 0 if !@ARGV;
-@deps = qw ( .git/HEAD .git/refs/heads .git/refs/tags );
+my @changelog_deps = qw ( .git/HEAD .git/refs/heads .git/refs/tags );
+
+my $branch;
+my $current_version;
+my @tags;
+my @all_tags;
+my $config;
+
+my $opt_log;
+my $opt_version;
+my $opt_branch;
+my $opt_update;
+my $opt_file;
+my $opt_start;
+my $opt_max;
+my $opt_width = 66;
+my $opt_width_fuzz = 8;
+my $opt_sep_width = 68;
+my $opt_format = 'internal'; # obs, internal
+my $opt_merge_msg_before = 1; # log auto generated pr merge message before the commit messages (vs. after)
+my $opt_join_author = 1; # join consecutive commit messages as long as they are by the same author
+my $opt_keep_date = 1; # don't join consecutive commit messages if they have different time stamps
+my $opt_default_email = 'opensuse-packaging(a)opensuse.org'; # default email to use in changelog
GetOptions(
'help' => sub { usage 0 },
'version' => \$opt_version,
+ 'branch' => \$opt_branch,
'update' => \$opt_update,
+ 'start=s' => \$opt_start,
+ 'format=s' => \$opt_format,
+ 'max=i' => \$opt_max,
+ 'width=i' => \$opt_width,
+ 'fuzz=i' => \$opt_width_fuzz,
+ 'merge-msg=s' => sub { $opt_merge_msg_before = ($_[1] eq 'after' ? 0 : 1) },
+ 'join-author!' => \$opt_join_author,
+ 'keep-date!' => \$opt_keep_date,
'log|changelog' => \$opt_log,
+ 'default-email=s' => \$opt_default_email,
) || usage 1;
-usage 1 if @ARGV > 1 || !($opt_log || $opt_version);
+# ensure we are used correctly
+usage 1 if @ARGV > 1 || !($opt_log || $opt_version || $opt_branch);
$opt_file = @ARGV ? shift : '-';
die "no git repo\n" unless -d ".git";
-if($opt_update && $opt_file ne '-' && -f($opt_file)) {
- $ok = 1;
+# if update option has been give write changelog only if git refs are newer
+exit 0 if $opt_update && $opt_file ne '-' && -f($opt_file) && !changelog_outdated($opt_file);
+
+$opt_max = 2 if $opt_version || $opt_branch;
- $t = (stat $opt_file)[9];
+# gather some data
+get_github_project;
+get_branch;
+get_log;
+fix_dates;
+get_tags;
+choose_tags;
+add_head_tag;
+get_version;
+
+# just print current branch
+if($opt_branch) {
+ open my $f, ">$opt_file";
+ print $f $config->{branch} ? $config->{branch} : "master", "\n";
+ close $f;
+
+ exit 0;
+}
- for (@deps) {
- $ok = 0 if (stat)[9] > $t;
+# just print current version
+if($opt_version) {
+ my $old_version;
+
+ if($opt_file ne '-' && open(my $f, $opt_file)) {
+ chomp($old_version = <$f>);
+ close $f;
+ }
+
+ if($config->{version} ne $old_version) {
+ open my $f, ">$opt_file";
+ print $f "$config->{version}\n";
+ close $f;
}
- exit 0 if $ok;
+ exit 0;
}
-for (`git branch`) {
- if(/^\*\s+(\S+)/) {
- $branch = $1;
- last;
+# set start tag
+if($opt_start) {
+ my $x = is_formatted_tag $opt_start;
+ die "$opt_start: not a valid start tag\n" if !$x;
+ $x->{branch} = $config->{branch} if !$x->{branch};
+ $config->{start} = $x;
+}
+
+format_all_logs;
+
+open my $f, ">$opt_file";
+
+print $f $_->{formatted} for @{$config->{log}};
+
+close $f;
+
+exit 0;
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# usage(exit_code)
+#
+# Print help message and exit.
+# - exit_code: exit code
+#
+# Function does not return.
+#
+sub usage
+{
+ my $err = shift;
+
+ print <<" usage";
+Usage: git2log [OPTIONS] [FILE]
+Create changelog and project version from git repo.
+ --changelog Write changelog to FILE.
+ --version Write version number to FILE.
+ --branch Write current branch to FILE.
+ --start START_TAG Start with tag START_TAG.
+ --max N Write at most MAX long entries.
+ --update Write changelog or version only if FILE is outdated.
+ --format FORMAT Write log using FORMAT. Supported FORMATs are 'internal' (default) and 'obs'.
+ --width WIDTH Reformat log entries to be max WIDTH chars wide.
+ --fuzz FUZZ Allow log lines to be up to FUZZ chars longer as WIDTH to avoid
+ line breaks leaving tiny bits on the last line.
+ --merge-msg WHERE Log message about merges before or after the actual merge commit messages.
+ Valid values for WHERE are 'after' and 'before' (default).
+ --join-author Join consecutive commits as long as they are by the same author. (default)
+ --no-join-author Keep consecutive commits by the same author separate.
+ --keep-date Join consecutive commits only if they have the same date. (default)
+ --no-keep-date Join consecutive commits even if dates differ.
+ --default-email Use this email in changelog entries if no other suitable email could be
+ determined (default: opensuse-packaging\(a)opensuse.org)
+ --help Print this help text.
+ usage
+
+ exit $err;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# res = changelog_outdated(file)
+#
+# Return status of changelog file.
+# - file: changelog file name
+# - res: status
+# 1: file is newer than the last git repo change and should be updated
+# 0: file is still recent enough
+#
+# Relies on global var @changelog_deps.
+#
+sub changelog_outdated
+{
+ my $file = $_[0];
+
+ my $changelog_time = (stat $file)[9];
+
+ return 1 if !defined $changelog_time;
+
+ for (@changelog_deps) {
+ return 1 if (stat)[9] > $changelog_time;
+ }
+
+ return 0;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_github_project()
+#
+# Set $config->{github_project} to the github project name.
+#
+sub get_github_project
+{
+ if(`git config remote.origin.url` =~ m#github.com[:/]+(\S+/\S+)#) {
+ $config->{github_project} = $1;
+ $config->{github_project} =~ s/\.git$//;
}
}
-$branch = "master" if $branch eq '(no';
-die "no branch?\n" unless $branch;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_version()
+#
+# Set $config->{branch} and $config->{version} to the current branch and
+# version info.
+#
+# This might be taken directly from HEAD if HEAD is tagged or otherwise be
+# exprapolated from the most recent tag (cf. add_head_tag()).
+#
+sub get_version
+{
+ $config->{version} = "0.0";
-# print STDERR "writing log for branch $branch\n";
+ my $tag = $config->{log}[0]{tags}[0];
-@tags = `git tag`;
+ if($tag->{version}) {
+ $config->{version} = $tag->{version};
+ $config->{branch} = $tag->{branch};
+ }
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_tags()
+#
+# Parse $config->{raw_log}, extract tag names, and split into per-tag
+# sections.
+#
+# Only tags recognized by is_formatted_tag() are considered.
+#
+# The parsed logs is stored in $config->{log}, an array of log sections.
+# Each section is a hash with these keys:
+# - 'tags': array of tags for this section
+# - 'commit': git commit id associated with these tags
+# - 'lines': git log lines
+#
+sub get_tags
+{
+ my $log_entry;
+
+ for (@{$config->{raw_log}}) {
+ if(/^commit (\S+)( \((.*)\))?/) {
+ my $commit = $1;
+ my $tag_list = $3;
+ my $xtag;
+
+ for my $t (split /, /, $tag_list) {
+ if($t =~ /tag: (\S+)/) {
+ my $tag = $1;
+ my $x = is_formatted_tag $tag;
+ push @$xtag, $x if $x;
+ }
+ }
-chomp @tags;
+ if($xtag) {
+ if($log_entry) {
+ push @{$config->{log}}, $log_entry;
+ last if $opt_max && @{$config->{log}} >= $opt_max;
+ }
+ $log_entry = { commit => $commit, tags => $xtag };
+ }
+ else {
+ $log_entry = { commit => $commit } if !$log_entry;
+ }
+ }
-for (@tags) {
- if(/^\d/) {
- s/(\d+)/sprintf "%04d", $1/eg;
- push @ntags, $_;
+ push @{$log_entry->{lines}}, $_ if $log_entry;
}
- elsif(s/^$branch\-//) {
- s/(\d+)/sprintf "%04d", $1/eg;
- push @ntags, "$branch-$_";
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_log()
+#
+# Read git log and store lines as array in $config->{raw_log} (trailing
+# newlines removed).
+#
+sub get_log
+{
+ chomp(@{$config->{raw_log}} = `git log --pretty=medium --date=raw --topo-order --decorate`);
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# hash_ref = is_formatted_tag(tag_name)
+#
+# Parse tag and return hash ref with branch and version number parts or
+# undef if it doesn't match.
+# - tag_name: tag as string
+# - hash_ref: hash ref with internal tag representation (with keys 'branch' and 'version').
+#
+# This expects tags of the form "VERSION" or "BRANCH-VERSION" where VERSION
+# consists of decimal numbers separated by dots '.' and BRANCH can be any
+# string.
+# (Note: it doesn't really have to be the name of an existing branch.)
+#
+# Tags not conforming to this convention are ignored.
+#
+sub is_formatted_tag
+{
+ if($_[0] =~ /^((.+)-)?((\d+\.)*\d+)$/) {
+ return { branch => $2, version => $3 }
}
+
+ return undef;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# get_branch()
+#
+# Get currently active git branch and store in $config->{branch}.
+#
+# 'master' branch is represented by empty 'branch' key.
+#
+sub get_branch
+{
+ chomp(my $branch = `git rev-parse --abbrev-ref HEAD`);
+
+ $branch = "" if $branch eq 'master';
+
+ $config->{branch} = $branch;
}
-@tags = sort @ntags;
-die "no tags at all?\n" unless @tags;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# res = tag_sort(a, b)
+#
+# Compare 2 tags.
+# - a, b: refs to tag hash
+# - res: -1, 0, 1
+#
+# This is used when we have to decide between alternative tags.
+# (Prefer 'lesser' variant.)
+#
+sub tag_sort
+{
+ my ($x, $y);
+
+ $x = length $a->{version};
+ $y = length $b->{version};
-$current_version = $tags[-1];
-$current_version =~ s/(\d+)/$1 + 0/eg;
+ # longer version number first
+ return $y <=> $x if $y <=> $x;
-if(`git log --pretty=medium --date=iso '$current_version..HEAD'`) {
- $current_version =~ s/(\d+)$/$1 + 1/e;
+ return $a->{branch} cmp $b->{branch};
}
-$current_version =~ s/^$branch\-//;
-if($opt_version) {
- open F, ">$opt_file";
- print F "$current_version\n";
- close F;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# str = tag_to_str(tag_ref)
+#
+# Convert tag into string.
+# - tag_ref: ref to hash with 'branch' and 'version' keys
+# - str: string (e.g. "foo-1.44")
+#
+# 'master' branch is represented by missing/empty 'branch' key.
+#
+sub tag_to_str
+{
+ my $tag = $_[0];
+ my $str;
- exit 0;
+ $str = "$tag->{branch}-" if $tag->{branch} ne "";
+ $str .= $tag->{version};
+
+ return $str;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# str = tags_to_str(tag_array_ref)
+#
+# Convert array of tags into string.
+# - tag_array_ref: ref to array of tags
+# - str: string (e.g. "(tag1, tag2)"
+#
+# This function is used only internally for debugging.
+#
+sub tags_to_str
+{
+ my $tags = $_[0];
+ my $str;
+
+ for my $t (@$tags) {
+ $str .= ", " if $str;
+ $str .= tag_to_str $t;
+ }
+
+ return "($str)";
}
-if($branch ne 'master') {
- for ($i = 0; $i < @tags; $i++) {
- if($tags[$i] =~ /^$branch\-(\S+)/) {
- $i2 = $i;
- $bi = $1;
- last;
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# choose_tags()
+#
+# Scan commit messages and extract tag & branch information.
+#
+# This stores the tag/branch info in $config->{log}[]{tags}.
+#
+sub choose_tags
+{
+ my $branch = $config->{branch};
+
+ for my $x (@{$config->{log}}) {
+ # printf "# %s\n", tags_to_str($x->{tags});
+
+ # no tag info? -> ignore
+ next if !$x->{tags};
+
+ # single tag? -> remember branch info
+ if(@{$x->{tags}} == 1) {
+ $branch = $x->{tags}[0]{branch};
+ next;
}
+
+ # several tags? -> choose one
+
+ # any with current branch name?
+ my @t = grep { $_->{branch} eq $branch } @{$x->{tags}};
+
+ # no? -> choose among all
+ @t = @{$x->{tags}} if @t == 0;
+
+ # prefer longest version number, then alphanumerically smallest branch name
+ @t = sort tag_sort @t;
+
+ $branch = $t[0]{branch};
+ $x->{tags} = [ $t[0] ];
+
+ # printf "X %s\n", tags_to_str($x->{tags});
}
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# add_head_tag()
+#
+# Suggest tag for HEAD if there isn't one.
+#
+# Basically, use branch + version from most recent tag and increment version.
+#
+sub add_head_tag
+{
+ return if @{$config->{log}} < 2;
- # print STDERR ">> $branch-$bi\n";
+ # HEAD tagged already?
+ return if $config->{log}[0]{tags};
- warn "no tags in this branch yet\n" unless $bi;
+ # the first tagged commit if HEAD isn't tagged
+ my $tag = { %{$config->{log}[1]{tags}[0]} };
- for ($i = 0; $i < $i2; $i++) {
- if($tags[$i] ge $bi) {
- if($tags[$i] eq $bi) {
- $i1 = $i;
+ # increment version
+ $tag->{version} =~ s/(\d+)$/$1 + 1/e;
+
+ $config->{log}[0]{tags}[0] = $tag;
+
+ # remember that the tag was generated
+ $config->{log}[0]{was_untagged} = 1;
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# fix_dates()
+#
+# Adjust time stamps in entire git log.
+#
+# The time stamps of the git commits are not necessarily ordered by date.
+# But the generated changelog is required to have a strictly monotonic time.
+#
+# We do this by going through the log in reverse and rewriting any dates we
+# find whenever the date decreases.
+#
+# A minimum time difference of 1 second beween entries is maintained.
+#
+# Not very subtle but it works.
+#
+sub fix_dates
+{
+ my $last_date;
+
+ for (reverse @{$config->{raw_log}}) {
+ # e.g. "Date: 1443184889 +0200"
+ if(/^(Date:\s+)(\S+)(\s+\S+)/) {
+ if(defined $last_date && $2 < $last_date) {
+ $_ = "$1$last_date$3\n";
}
- elsif($i > 0) {
- $i1 = $i - 1;
+ else {
+ $last_date = $2;
}
- last;
+
+ # ensure a minimal time gap of 1 second
+ $last_date += 1;
}
}
+}
+
- splice @tags, $i1, $i2 - $i1;
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# format_all_logs()
+#
+# Format the entire git log.
+#
+# This is done for every code version individually (the log has already been
+# split accordingly).
+#
+# If $config->{start} is set, use this as starting point. Else format the
+# entire git log.
+#
+sub format_all_logs
+{
+ # check if start tag actually exists - if not, print nothing
+ if($config->{start}) {
+ my $tag_found;
+ for (@{$config->{log}}) {
+ $tag_found = 1, last if grep { tag_to_str($config->{start}) eq tag_to_str($_) } @{$_->{tags}};
+ }
+ return if !$tag_found;
+ }
+
+ for (@{$config->{log}}) {
+ if($config->{start}) {
+ # stop if we meet the start tag
+ last if grep { tag_to_str($config->{start}) eq tag_to_str($_) } @{$_->{tags}};
+ }
+ format_log $_;
+ }
}
-map { s/(\d+)/$1 + 0/eg } @tags;
-push @tags, "HEAD";
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# format_log(log)
+#
+# Format log messages.
+# - log: is an array ref with individual commits
+#
+# All commits belong to a specific code version (stored in $log->{tag}).
+# $log->{formatted} holds the result.
+#
+# The process is done in several individual steps, documented below in the code.
+#
+sub format_log
+{
+ my $log = $_[0];
+
+ my $merge;
+ my $commit;
+ my $saved_commit;
+ my $commits;
+
+ for (@{$log->{lines}}) {
+ if(/^commit (\S+)/) {
+ $commit = { ref => $1 };
+ push @{$commits}, $commit;
+
+ if(
+ $merge &&
+ $merge->{merge_end} eq substr($commit->{ref}, 0, length($merge->{merge_end}))
+ ) {
+ undef $merge;
+ }
+
+ if($merge) {
+ $commit->{merge_ref} = $merge->{ref};
+ $commit->{date} = $merge->{date};
+ # add to all commits so it's not lost when we re-arrange
+ $commit->{merge_msg} = $merge->{msg} if $merge->{msg};
+ # saved entry no longer needed
+ undef $saved_commit;
+ }
+
+ next;
+ }
+
+ if(/^Merge: (\S+)/) {
+ if($commit) {
+ $merge = { merge_end => $1, ref => $commit->{ref} } unless $merge;
+ $saved_commit = pop @{$commits};
+ }
+ undef $commit;
+ next;
+ }
+
+ if(/^Date:\s+(\S.*)/) {
+ if($commit) {
+ $commit->{date} = $1 if !$commit->{date};
+ }
+ elsif($merge) {
+ $merge->{date} = $1 if !$merge->{date};
+ }
+ next;
+ }
+
+ if(/^Author:\s+(\S.*)/) {
+ $commit->{author} = $1 if $commit;
+ $merge->{author} = $1 if $merge && !$merge->{author};
+ next;
+ }
+
+ if($commit) {
+ push @{$commit->{lines}}, $_ if s/^ //;
+ }
+ elsif($merge && !$merge->{msg}) {
+ if(/^ Merge pull request (#\d+) from (\S+)/) {
+ if($config->{github_project}) {
+ $merge->{msg} = "merge gh#$config->{github_project}$1";
+ }
+ else {
+ $merge->{msg} = "merge pr $2";
+ }
+ }
+ elsif(/^ Merge branch '([^']+)'/) {
+ $merge->{msg} = "merge branch $1";
+ }
+ }
+ }
+
+ # it can happen that there's a lonely merge commit left at the end
+ if($merge && $saved_commit) {
+ $saved_commit->{merge_ref} = $merge->{ref};
+ $saved_commit->{date} = $merge->{date};
+ $saved_commit->{author} = $merge->{author};
+ $saved_commit->{merge_msg} = $merge->{msg} if $merge->{msg};
+ $saved_commit->{formatted} = [];
+
+ push @{$commits}, $saved_commit;
+ }
+
+ # Note: the individual steps below work on the array @$commits and modify
+ # its content.
+
+ # step 1
+ # - if there are paragraphs starting with '@log@' or '@+log@'
+ # - delete first paragraph (short summary)
+ # - else
+ # - keep only first paragraph
+ # - if there is a paragraph starting with '@-log', delete entire log
+ # - tag commits that have a '@log@' tag so we can delete untagged commits
+ # belonging to the same merge commit later
+
+ my $tagged_merges = {};
+
+ for my $commit (@$commits) {
+ my $para_cnt = 0;
+ my $delete_all = 0;
+ my $delete_first = 0;
+ for (@{$commit->{lines}}) {
+ $para_cnt++ if $_ eq "";
+ $para_cnt = 0, $delete_first = 1 if /^\@\+log\@/;
+ $delete_all = 1 if /^\@\-log\@/;
+ if(/^\@log\@/) {
+ $para_cnt = 0;
+ $commit->{clear} = 1;
+ $tagged_merges->{$commit->{merge_ref}} = 1 if $commit->{merge_ref} || $log->{was_untagged};
+ }
+ $_ = undef if $para_cnt;
+ }
+ shift @{$commit->{lines}} if $delete_first;
+ $commit->{lines} = [] if $delete_all;
+ }
-# print Dumper(\@tags);
+ # step 2
+ # - clean up tagged commits or commits belonging to tagged merges
-open F, ">$opt_file";
+ for my $commit (@$commits) {
+ next unless $commit->{clear} || $tagged_merges->{$commit->{merge_ref}};
+ for (@{$commit->{lines}}) {
+ last if /^\@\+?log\@/;
+ $_ = undef;
+ }
+ }
-for ($i = @tags - 1; $i > 0; $i--) {
- $date = undef;
- @t = `git log --pretty=medium --date=iso '$tags[$i-1]..$tags[$i]'`;
+ # step 3
+ # - join lines
- # print "\n--- $tags[$i-1]..$tags[$i] ---\n", @t, "---\n";
+ for my $commit (@$commits) {
+ my $lines;
+ my $line;
+
+ for (@{$commit->{lines}}) {
+ next if $_ eq "";
+ if(
+ s/^\s*[+\-][\-\s]*// ||
+ s/^\@\+?log\@// ||
+ $line eq ""
+ ) {
+ s/^\s*//;
+ push @$lines, $line if $line ne "";
+ $line = $_;
+ }
+ else {
+ s/^\s*//;
+ $line .= " " if $line ne "";
+ $line .= $_;
+ }
+ }
+ push @$lines, $line if $line ne "";
- undef @t2;
- $merge = 0;
- for (@t) {
- $merge = 1 if /^Merge: /;
- $merge = 0 if /^commit /;
- push @t2, $_ if !$merge;
+ $commit->{formatted} = $lines if $lines;
}
- @t = @t2;
- undef @t2;
- $detail = 0;
- for (@t) {
- $detail = 1 if /^ $/;
- $detail = 0 if /^commit /;
- if($detail && /^ [^\-\s]/) {
- # push @t2, "# $_";
+ # step 4
+ # - fix small glitches
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted};
+ for (@{$commit->{formatted}}) {
+ s/(fate|bnc|bsc)\s*(#\d+)/\L$1\E$2/ig;
+ }
+ }
+
+ # step 5
+ # - add merge info at the top or bottom (depending on $opt_merge_msg_before)
+
+ my $merge_logged;
+
+ for my $commit ($opt_merge_msg_before ? reverse(@$commits) : @$commits) {
+ next unless $commit->{formatted};
+
+ if($commit->{merge_ref} && !$merge_logged->{$commit->{merge_ref}}) {
+ $merge_logged->{$commit->{merge_ref}} = 1;
+ if($commit->{merge_msg}) {
+ if($opt_merge_msg_before) {
+ unshift @{$commit->{formatted}}, $commit->{merge_msg};
+ }
+ else {
+ push @{$commit->{formatted}}, $commit->{merge_msg};
+ }
+ }
+ }
+ }
+
+ # step 6
+ # - join commit messages with same author (optionally even with different dates)
+
+ my $commit0;
+
+ for my $commit (@$commits) {
+ next if !$commit->{formatted};
+ $commit0 = $commit, next if !$commit0;
+
+ if(
+ # $commit->{merge_ref} eq $commit0->{merge_ref} &&
+ (
+ $opt_join_author && ($commit->{author} eq $commit0->{author})
+ && (!$opt_keep_date || $commit->{date} eq $commit0->{date})
+ )
+ || $opt_format eq 'internal'
+ ) {
+ unshift @{$commit0->{formatted}}, @{$commit->{formatted}};
+ delete $commit->{formatted};
+ }
+ else {
+ $commit0 = $commit;
+ }
+ }
+
+ # step 7
+ # - add version tag at the end of the first log entry
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted};
+
+ if($opt_format eq 'obs') {
+ push @{$commit->{formatted}}, $log->{tags}[0]{version} if defined $log->{tags}[0]{version};
}
else {
- push @t2, $_;
+ # push @{$commit->{formatted}}, tag_to_str($log->{tags}[0]);
}
+
+ last;
}
- @t = @t2;
- # print "\n--- $tags[$i-1]..$tags[$i] ---\n", @t;
+ # step 8
+ # - add line breaks
- chomp @t;
- for (@t) {
- if(/^Date:\s*(\S+)/) {
- $date = $1;
- last;
+ for my $commit (@$commits) {
+ next unless $commit->{formatted};
+ for (@{$commit->{formatted}}) {
+ $_ = add_line_breaks $_;
}
}
- @t = grep { !/^(commit|Author:|Date:|Merge:|\s*$)|created.*tag/ } @t;
- if(@t) {
- # rewrite a bit to have it look more consistent
- map { s/(fate|bnc)#/$1 #/g } @t;
- map { s/\(#/(bnc #/g } @t;
- map { s/bug\s*#/bnc #/g } @t;
- map { s/feat(\.|ure)?\s*#?(\d+)/fate #$2/g } @t;
- map { s/^ {4}// } @t;
- map { s/^ {8}// } @t;
- map { s/^ +/ / } @t;
- map { s/^\s*[+\-][\-\s]*/- / } @t;
- map { s/^([^ \-])/- $1/ } @t;
- map { s/^/\t/ } @t;
- map { s/\\'/'/ } @t;
-# print "\n--- $tags[$i-1]..$tags[$i] ---\n", join("\n", @t);
+ # step 9
+ # - generate final log message
+ #
+ # note: non-(open)suse email addresses are replaced by $opt_default_email
+
+ my $formated_log;
+
+ for my $commit (@$commits) {
+ next unless $commit->{formatted} && @{$commit->{formatted}};
+
+ if($opt_format eq 'obs') {
+ $formated_log .= "-" x $opt_sep_width . "\n";
+ $formated_log .= format_date_obs($commit->{date});
+ }
+ else {
+ $formated_log .= format_date_iso($commit->{date});
+ }
+ if($opt_format eq 'obs') {
+ my $auth = $commit->{author};
+ $auth =~ s/^.*<//;
+ $auth =~ s/>.*$//;
+ # replace non-suse e-mail addresses with a generic one
+ if($auth !~ /\(a)(suse\.(com|cz|de)|opensuse\.org)$/) {
+ $auth = $opt_default_email;
+ }
+ $formated_log .= " - $auth\n\n";
+ }
+ else {
+ $formated_log .= ":\t" . tag_to_str($log->{tags}[0]) . "\n";
+ }
+
+ for (@{$commit->{formatted}}) {
+ s/^/\t/mg if $opt_format eq 'internal';
+ $formated_log .= "$_\n";
+ }
- $t = $tags[$i];
- $t = "${branch}-$t" if $branch ne 'master' && $t eq "HEAD";
- $t =~ s/HEAD/$current_version/;
- print F "$date:\t$t\n";
- print F join("\n", @t), "\n\n";
+ $formated_log .= "\n";
}
+
+ $log->{formatted} = $formated_log;
}
-close F;
-sub usage
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# new_text = add_line_breaks(text)
+#
+# Add line breaks to text.
+# - text: some text
+# - new_text: same text, reformatted
+#
+# Lines are formatted to have a maximal length of $opt_width. If this causes
+# the last line to be shorter than $opt_width_fuzz, it is appended to the
+# previous line.
+#
+sub add_line_breaks
{
- my $err = shift;
+ my @words = split /\s+/, @_[0];
+ my $remaining_len = length(join '', @words);
- print <<" usage";
-Usage: git2log [OPTIONS] [FILE]
-Create changelog and project version from git repo.
- --changelog Write changelog to FILE.
- --version Write version number to FILE.
- --update Write changelog or version only if FILE is outdated.
- --help Print this help text.
- usage
+ my $str = shift(@words);
+ my $len = length $str;
- exit $err;
+ my $next_len;
+ my $word_len;
+
+ for (@words) {
+ $word_len = length;
+ $remaining_len -= $word_len;
+ $next_len = $len + $word_len + 1;
+ if(
+ $next_len >= $opt_width &&
+ $next_len + $remaining_len + 1 >= $opt_width + $opt_width_fuzz
+ ) {
+ $str .= "\n $_";
+ $len = $word_len;
+ }
+ else {
+ $str .= " $_";
+ $len += $word_len + 1;
+ }
+ }
+
+ return "- " . $str;
}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# seconds = raw_date_to_s(git_date)
+#
+# Convert git raw date to seconds.
+# - git_date: raw git format (e.g. "1443184889 +0200")
+# - seconds: the seconds part (e.g. "1443184889")
+#
+sub raw_date_to_s
+{
+ return (split / /, $_[0])[0];
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# date = format_date_obs(git_date)
+#
+# Convert git raw date to obs format.
+# - git_date: raw git format (e.g. "1443184889 +0200")
+# - date: obs format ("Fri Sep 25 12:41:29 UTC 2015")
+#
+sub format_date_obs
+{
+ my @d = gmtime(raw_date_to_s($_[0]));
+
+ return
+ qw(Sun Mon Tue Wed Thu Fri Sat)[$d[6]] . " " .
+ qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[$d[4]] . " " .
+ $d[3] . " " .
+ sprintf("%02d:%02d:%02d", $d[2], $d[1], $d[0]) . " UTC " .
+ (1900 + $d[5]);
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# date = format_date_iso(git_date)
+#
+# Convert git raw date to iso format.
+# - git_date: raw git format (e.g. "1443184889 +0200")
+# - date: obs format ("2015-09-25")
+#
+sub format_date_iso
+{
+ my @d = gmtime(raw_date_to_s($_[0]));
+
+ return sprintf("%04d-%02d-%02d", 1900 + $d[5], $d[4] + 1, $d[3]);
+}
1
0
Hello community,
here is the log from the commit of package openscap for openSUSE:Factory checked in at 2018-04-27 16:08:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/openscap (Old)
and /work/SRC/openSUSE:Factory/.openscap.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openscap"
Fri Apr 27 16:08:52 2018 rev:56 rq:601561 version:1.2.16
Changes:
--------
--- /work/SRC/openSUSE:Factory/openscap/openscap.changes 2018-03-07 10:35:17.353154897 +0100
+++ /work/SRC/openSUSE:Factory/.openscap.new/openscap.changes 2018-04-27 16:09:04.962818068 +0200
@@ -1,0 +2,6 @@
+Thu Apr 26 12:56:42 UTC 2018 - meissner(a)suse.com
+
+- openscap-new-suse.patch: handle SLE15 and openSUSE Leap 42.3 and 15.0
+ (bsc#1091040)
+
+-------------------------------------------------------------------
New:
----
openscap-new-suse.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ openscap.spec ++++++
--- /var/tmp/diff_new_pack.j2ZPz7/_old 2018-04-27 16:09:05.626793715 +0200
+++ /var/tmp/diff_new_pack.j2ZPz7/_new 2018-04-27 16:09:05.630793568 +0200
@@ -36,6 +36,7 @@
Source4: scap-yast2sec-oval.xml
Source5: oscap-scan.service
Source6: oscap-scan.sh
+Patch0: openscap-new-suse.patch
Url: http://www.open-scap.org/
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: doxygen
@@ -174,6 +175,7 @@
%prep
%setup -q
+%patch0 -p1
%build
++++++ openscap-new-suse.patch ++++++
Index: openscap-1.2.16/cpe/openscap-cpe-dict.xml
===================================================================
--- openscap-1.2.16.orig/cpe/openscap-cpe-dict.xml
+++ openscap-1.2.16/cpe/openscap-cpe-dict.xml
@@ -133,6 +133,14 @@
<title xml:lang="en-us">SUSE Linux Enterprise Desktop 12</title>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.sled:def:12</check>
</cpe-item>
+ <cpe-item name="cpe:/o:suse:sles:15">
+ <title xml:lang="en-us">SUSE Linux Enterprise Server 15</title>
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.sles:def:15</check>
+ </cpe-item>
+ <cpe-item name="cpe:/o:suse:sled:15">
+ <title xml:lang="en-us">SUSE Linux Enterprise Desktop 15</title>
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.sled:def:15</check>
+ </cpe-item>
<cpe-item name="cpe:/o:opensuse:opensuse:11.4">
<title xml:lang="en-us">openSUSE 11.4</title>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:114</check>
@@ -145,14 +153,22 @@
<title xml:lang="en-us">openSUSE 13.2</title>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:132</check>
</cpe-item>
- <cpe-item name="cpe:/o:novell:leap:42.1">
+ <cpe-item name="cpe:/o:opensuse:leap:42.1">
<title xml:lang="en-us">openSUSE 42.1</title>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:421</check>
</cpe-item>
- <cpe-item name="cpe:/o:novell:leap:42.2">
+ <cpe-item name="cpe:/o:opensuse:leap:42.2">
<title xml:lang="en-us">openSUSE 42.2</title>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:422</check>
</cpe-item>
+ <cpe-item name="cpe:/o:opensuse:leap:42.3">
+ <title xml:lang="en-us">openSUSE Leap 42.3</title>
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:423</check>
+ </cpe-item>
+ <cpe-item name="cpe:/o:opensuse:leap:15.0">
+ <title xml:lang="en-us">openSUSE Leap 15.0</title>
+ <check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:150</check>
+ </cpe-item>
<cpe-item name="cpe:/o:opensuse:opensuse">
<title xml:lang="en-us">openSUSE All Versions</title>
<check system="http://oval.mitre.org/XMLSchema/oval-definitions-5" href="openscap-cpe-oval.xml">oval:org.open-scap.cpe.opensuse:def:1</check>
Index: openscap-1.2.16/cpe/openscap-cpe-oval.xml
===================================================================
--- openscap-1.2.16.orig/cpe/openscap-cpe-oval.xml
+++ openscap-1.2.16/cpe/openscap-cpe-oval.xml
@@ -449,6 +449,34 @@
</criteria>
</definition>
+ <definition class="inventory" id="oval:org.open-scap.cpe.sles:def:15" version="1">
+ <metadata>
+ <title>SUSE Linux Enterprise Server 15</title>
+ <affected family="unix">
+ <platform>SUSE Linux Enterprise Server 15</platform>
+ </affected>
+ <reference ref_id="cpe:/o:suse:sles:15" source="CPE"/>
+ <description>The operating system installed on the system is SUSE Linux Enterprise Server 15</description>
+ </metadata>
+ <criteria>
+ <criterion comment="SLES 15 is installed" test_ref="oval:org.open-scap.cpe.sles:tst:15"/>
+ </criteria>
+ </definition>
+
+ <definition class="inventory" id="oval:org.open-scap.cpe.sled:def:15" version="1">
+ <metadata>
+ <title>SUSE Linux Enterprise Desktop 15</title>
+ <affected family="unix">
+ <platform>SUSE Linux Enterprise Desktop 15</platform>
+ </affected>
+ <reference ref_id="cpe:/o:suse:sled:15" source="CPE"/>
+ <description>The operating system installed on the system is SUSE Linux Enterprise Desktop 15</description>
+ </metadata>
+ <criteria>
+ <criterion comment="SLED 15 is installed" test_ref="oval:org.open-scap.cpe.sled:tst:15"/>
+ </criteria>
+ </definition>
+
<definition class="inventory" id="oval:org.open-scap.cpe.opensuse:def:1" version="1">
<metadata>
<title>openSUSE All Versions</title>
@@ -519,17 +547,43 @@
</definition>
<definition class="inventory" id="oval:org.open-scap.cpe.opensuse:def:422" version="1">
<metadata>
- <title>openSUSE 42.2</title>
+ <title>openSUSE Leap 42.2</title>
<affected family="unix">
- <platform>openSUSE 42.2</platform>
+ <platform>openSUSE Leap 42.2</platform>
</affected>
<reference ref_id="cpe:/o:novell:leap:42.2" source="CPE"/>
- <description>The operating system installed on the system is openSUSE 42.2</description>
+ <description>The operating system installed on the system is openSUSE Leap 42.2</description>
</metadata>
<criteria>
<criterion comment="openSUSE 42.2 is installed" test_ref="oval:org.open-scap.cpe.opensuse:tst:422"/>
</criteria>
</definition>
+ <definition class="inventory" id="oval:org.open-scap.cpe.opensuse:def:423" version="1">
+ <metadata>
+ <title>openSUSE Leap 42.3</title>
+ <affected family="unix">
+ <platform>openSUSE Leap 42.3</platform>
+ </affected>
+ <reference ref_id="cpe:/o:novell:leap:42.3" source="CPE"/>
+ <description>The operating system installed on the system is openSUSE Leap 42.3</description>
+ </metadata>
+ <criteria>
+ <criterion comment="openSUSE 42.3 is installed" test_ref="oval:org.open-scap.cpe.opensuse:tst:423"/>
+ </criteria>
+ </definition>
+ <definition class="inventory" id="oval:org.open-scap.cpe.opensuse:def:150" version="1">
+ <metadata>
+ <title>openSUSE Leap 15.0</title>
+ <affected family="unix">
+ <platform>openSUSE Leap 15.0</platform>
+ </affected>
+ <reference ref_id="cpe:/o:novell:leap:15.0" source="CPE"/>
+ <description>The operating system installed on the system is openSUSE Leap 15.0</description>
+ </metadata>
+ <criteria>
+ <criterion comment="openSUSE 42.3 is installed" test_ref="oval:org.open-scap.cpe.opensuse:tst:423"/>
+ </criteria>
+ </definition>
<definition class="inventory" id="oval:org.open-scap.cpe.wrlinux:def:1" version="1" >
<metadata>
<title>Wind River Linux</title>
@@ -715,6 +769,11 @@
<object object_ref="oval:org.open-scap.cpe.sles-release:obj:1"/>
<state state_ref="oval:org.open-scap.cpe.sles:ste:12"/>
</rpminfo_test>
+ <rpminfo_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.sles:tst:15" version="1" check="at least one" comment="sles-release is version 15"
+ xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <object object_ref="oval:org.open-scap.cpe.sles-release:obj:1"/>
+ <state state_ref="oval:org.open-scap.cpe.sles:ste:15"/>
+ </rpminfo_test>
<rpminfo_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.sled:tst:10" version="1" check="at least one" comment="sled-release is version 10"
xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<object object_ref="oval:org.open-scap.cpe.sled-release:obj:1"/>
@@ -730,6 +789,11 @@
<object object_ref="oval:org.open-scap.cpe.sled-release:obj:1"/>
<state state_ref="oval:org.open-scap.cpe.sled:ste:12"/>
</rpminfo_test>
+ <rpminfo_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.sled:tst:15" version="1" check="at least one" comment="sled-release is version 15"
+ xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <object object_ref="oval:org.open-scap.cpe.sled-release:obj:1"/>
+ <state state_ref="oval:org.open-scap.cpe.sled:ste:15"/>
+ </rpminfo_test>
<rpminfo_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.opensuse:tst:1" version="1" check="at least one" comment="openSUSE-release is version 11.4"
xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<object object_ref="oval:org.open-scap.cpe.openSUSE-release:obj:1"/>
@@ -760,6 +824,16 @@
<object object_ref="oval:org.open-scap.cpe.openSUSE-release:obj:1"/>
<state state_ref="oval:org.open-scap.cpe.opensuse:ste:422"/>
</rpminfo_test>
+ <rpminfo_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.opensuse:tst:423" version="2" check="at least one" comment="openSUSE-release is version 42.2"
+ xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <object object_ref="oval:org.open-scap.cpe.openSUSE-release:obj:1"/>
+ <state state_ref="oval:org.open-scap.cpe.opensuse:ste:423"/>
+ </rpminfo_test>
+ <rpminfo_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.opensuse:tst:150" version="2" check="at least one" comment="openSUSE-release is version 42.2"
+ xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <object object_ref="oval:org.open-scap.cpe.openSUSE-release:obj:1"/>
+ <state state_ref="oval:org.open-scap.cpe.opensuse:ste:150"/>
+ </rpminfo_test>
<family_test check_existence="at_least_one_exists" id="oval:org.open-scap.cpe.wrlinux:tst:1" version="1" check="only one"
comment="Installed operating system is part of the Unix family."
xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent">
@@ -955,6 +1029,9 @@
<rpminfo_state id="oval:org.open-scap.cpe.sles:ste:12" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="pattern match">^12($|[^\d])</version>
</rpminfo_state>
+ <rpminfo_state id="oval:org.open-scap.cpe.sles:ste:15" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <version operation="pattern match">^15($|[^\d])</version>
+ </rpminfo_state>
<rpminfo_state id="oval:org.open-scap.cpe.sled:ste:10" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="pattern match">^10($|[^\d])</version>
</rpminfo_state>
@@ -964,6 +1041,9 @@
<rpminfo_state id="oval:org.open-scap.cpe.sled:ste:12" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="pattern match">^12($|[^\d])</version>
</rpminfo_state>
+ <rpminfo_state id="oval:org.open-scap.cpe.sled:ste:15" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <version operation="pattern match">^15($|[^\d])</version>
+ </rpminfo_state>
<rpminfo_state id="oval:org.open-scap.cpe.opensuse:ste:2" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<name operation="pattern match">^openSUSE-release</name>
</rpminfo_state>
@@ -982,6 +1062,12 @@
<rpminfo_state id="oval:org.open-scap.cpe.opensuse:ste:422" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="pattern match">^42.2$</version>
</rpminfo_state>
+ <rpminfo_state id="oval:org.open-scap.cpe.opensuse:ste:423" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <version operation="pattern match">^42.3$</version>
+ </rpminfo_state>
+ <rpminfo_state id="oval:org.open-scap.cpe.opensuse:ste:150" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
+ <version operation="pattern match">^15.0$</version>
+ </rpminfo_state>
<textfilecontent54_state
id="oval:org.open-scap.cpe.wrlinux-release:ste:8"
comment="Check the /etc/wrlinux-release file for VERSION 8 specification."
1
0
Hello community,
here is the log from the commit of package cobbler for openSUSE:Factory checked in at 2018-04-27 16:08:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cobbler (Old)
and /work/SRC/openSUSE:Factory/.cobbler.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cobbler"
Fri Apr 27 16:08:49 2018 rev:43 rq:601552 version:2.8.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/cobbler/cobbler.changes 2018-03-11 15:24:53.831977446 +0100
+++ /work/SRC/openSUSE:Factory/.cobbler.new/cobbler.changes 2018-04-27 16:09:01.538943645 +0200
@@ -1,0 +2,9 @@
+Thu Apr 26 12:09:52 UTC 2018 - pablo.suarezhernandez(a)suse.com
+
+- Escape shell parameters provided by the user for the
+ reposync action (CVE-2017-1000469) (bsc#1074594)
+
+- Added:
+ * escape-shell-parameters-provided-by-user-on-reposync.patch
+
+-------------------------------------------------------------------
New:
----
escape-shell-parameters-provided-by-user-on-reposync.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ cobbler.spec ++++++
--- /var/tmp/diff_new_pack.dVAOJW/_old 2018-04-27 16:09:02.754899048 +0200
+++ /var/tmp/diff_new_pack.dVAOJW/_new 2018-04-27 16:09:02.754899048 +0200
@@ -71,6 +71,8 @@
# PATCH-FIX-UPSTREAM https://github.com/cobbler/cobbler/pull/1811 (not merged yet)
Patch17: fix-script-endpoint-security-bug-1030582.patch
Patch18: fix-manpage-creation.patch
+# PATCH-FIX-UPSTREAM https://github.com/cobbler/cobbler/pull/1889 (not merged yet)
+Patch19: escape-shell-parameters-provided-by-user-on-reposync.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildArch: noarch
@@ -185,6 +187,7 @@
%patch16 -p1
%patch17 -p1
%patch18 -p1
+%patch19 -p1
%build
%{__python2} setup.py build
++++++ escape-shell-parameters-provided-by-user-on-reposync.patch ++++++
>From c4d0573eaf3dc9c8a9e3cb3d29829494af4f7543 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez(a)suse.com>
Date: Thu, 26 Apr 2018 12:37:43 +0100
Subject: [PATCH] Escape shell parameters provided by user on reposync action
(CVE-2017-1000469)
---
cobbler/action_reposync.py | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/cobbler/action_reposync.py b/cobbler/action_reposync.py
index cfdc41ad..2701d625 100644
--- a/cobbler/action_reposync.py
+++ b/cobbler/action_reposync.py
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
import os
import os.path
+import pipes
import urlgrabber
HAS_YUM = True
@@ -203,7 +204,7 @@ class RepoSync:
flags = blended.get("createrepo_flags","(ERROR: FLAGS)")
try:
# BOOKMARK
- cmd = "createrepo %s %s %s" % (" ".join(mdoptions), flags, dirname)
+ cmd = "createrepo %s %s %s" % (" ".join(mdoptions), flags, pipes.quote(dirname))
utils.subprocess_call(self.logger, cmd)
except:
utils.log_exc(self.logger)
@@ -227,7 +228,7 @@ class RepoSync:
dest_path = os.path.join(self.settings.webdir + "/repo_mirror", repo.name)
# FIXME: wrapper for subprocess that logs to logger
- cmd = "wget -N -np -r -l inf -nd -P %s %s" % (dest_path, repo_mirror)
+ cmd = "wget -N -np -r -l inf -nd -P %s %s" % (pipes.quote(dest_path), pipes.quote(repo_mirror))
rc = utils.subprocess_call(self.logger, cmd)
if rc != 0:
@@ -259,7 +260,7 @@ class RepoSync:
repo.mirror = "%s/" % repo.mirror
# FIXME: wrapper for subprocess that logs to logger
- cmd = "rsync -rltDv --copy-unsafe-links --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" % (spacer, repo.mirror, dest_path)
+ cmd = "rsync -rltDv --copy-unsafe-links --delete-after %s --delete --exclude-from=/etc/cobbler/rsync.exclude %s %s" % (spacer, pipes.quote(repo.mirror), pipes.quote(dest_path))
rc = utils.subprocess_call(self.logger, cmd)
if rc !=0:
@@ -325,7 +326,7 @@ class RepoSync:
if has_rpm_list:
self.logger.warning("warning: --rpm-list is not supported for RHN content")
rest = repo.mirror[6:] # everything after rhn://
- cmd = "%s %s --repo=%s --download_path=%s" % (cmd, self.rflags, rest, self.settings.webdir + "/repo_mirror")
+ cmd = "%s %s --repo=%s --download_path=%s" % (cmd, self.rflags, pipes.quote(rest), pipes.quote(self.settings.webdir + "/repo_mirror"))
if repo.name != rest:
args = { "name" : repo.name, "rest" : rest }
utils.die(self.logger,"ERROR: repository %(name)s needs to be renamed %(rest)s as the name of the cobbler repository must match the name of the RHN channel" % args)
@@ -392,7 +393,7 @@ class RepoSync:
if not has_rpm_list:
# if we have not requested only certain RPMs, use reposync
- cmd = "%s %s --config=%s --repoid=%s --download_path=%s" % (cmd, self.rflags, temp_file, repo.name, self.settings.webdir + "/repo_mirror")
+ cmd = "%s %s --config=%s --repoid=%s --download_path=%s" % (cmd, self.rflags, temp_file, pipes.quote(repo.name), pipes.quote(self.settings.webdir + "/repo_mirror"))
if repo.arch != "":
if repo.arch == "x86":
repo.arch = "i386" # FIX potential arch errors
@@ -420,7 +421,7 @@ class RepoSync:
cmd = "/usr/bin/dnf download"
else:
cmd = "/usr/bin/yumdownloader"
- cmd = "%s %s %s --disablerepo=* --enablerepo=%s -c %s --destdir=%s %s" % (cmd, extra_flags, use_source, repo.name, temp_file, dest_path, " ".join(repo.rpm_list))
+ cmd = "%s %s %s --disablerepo=* --enablerepo=%s -c %s --destdir=%s %s" % (cmd, extra_flags, use_source, pipes.quote(repo.name), temp_file, pipes.quote(dest_path), " ".join(repo.rpm_list))
# now regardless of whether we're doing yumdownloader or reposync
# or whether the repo was http://, ftp://, or rhn://, execute all queued
@@ -510,7 +511,7 @@ class RepoSync:
dists = ",".join(repo.apt_dists)
components = ",".join(repo.apt_components)
- mirror_data = "--method=%s --host=%s --root=%s --dist=%s --section=%s" % (method,host,mirror,dists,components)
+ mirror_data = "--method=%s --host=%s --root=%s --dist=%s --section=%s" % (pipes.quote(method), pipes.quote(host), pipes.quote(mirror), pipes.quote(dists), pipes.quote(components))
rflags = "--nocleanup"
for x in repo.yumopts:
@@ -519,6 +520,7 @@ class RepoSync:
else:
rflags += " %s" % x
cmd = "%s %s %s %s" % (mirror_program, rflags, mirror_data, dest_path)
+ cmd = "%s %s %s %s" % (mirror_program, rflags, mirror_data, pipes.quote(dest_path))
if repo.arch == "src":
cmd = "%s --source" % cmd
else:
--
2.15.1
1
0