Skip to content

Commit

Permalink
Introduce a doc/changelog.yml file.
Browse files Browse the repository at this point in the history
This will be the authoritative source for all changes across all branches. CHANGES and package.xml will be built from this source.
The idea is to keep this changelog.yml file the same in all branches, so that it's much easier to merge/cherry-pick commits including the changelog from one branch to the other without conflicts.
Beside that, it's easier to amend a changelog and update all the other changelogs with a single horde-components call.
Finally, this will allow us to automatically build chnangelogs for bundles in the future.
  • Loading branch information
yunosh committed Oct 25, 2017
1 parent 830eeb2 commit 04a4b5b
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 11 deletions.
28 changes: 23 additions & 5 deletions lib/Components/Component/Source.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,17 +214,35 @@ public function changed(
$log, Components_Helper_ChangeLog $helper, $options
)
{
$file = $helper->changelogYml($log, $options);
if ($file && !empty($options['commit'])) {
$options['commit']->add($file, $this->_directory);
}
if (empty($options['nopackage'])) {
$file = $helper->packageXml(
$log, $this->getPackageXml(), $this->getPackageXmlPath(), $options
);
if ($helper->changelogFileExists()) {
$file = $helper->updatePackage(
$this->getPackageXml(),
$this->getPackageXmlPath(),
$options
);
} else {
$file = $helper->packageXml(
$log,
$this->getPackageXml(),
$this->getPackageXmlPath(),
$options
);
}
if ($file && !empty($options['commit'])) {
$options['commit']->add($file, $this->_directory);
}
}

if (empty($options['nochanges'])) {
$file = $helper->changes($log, $this->_directory, $options);
if ($helper->changelogFileExists()) {
$file = $helper->updateChanges($options);
} else {
$file = $helper->changes($log, $options);
}
if ($file && !empty($options['commit'])) {
$options['commit']->add($file, $this->_directory);
}
Expand Down
190 changes: 189 additions & 1 deletion lib/Components/Helper/ChangeLog.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@
*/
class Components_Helper_ChangeLog
{
/** Path to the .horde.yml file. */
const HORDE_INFO = '/.horde.yml';

/** Path to the changelog.yml file. */
const CHANGELOG = '/doc/changelog.yml';

/** Path to the changelog.yml file up to Horde 5. */
const CHANGELOG_H5 = '/docs/changelog.yml';

/** Path to the CHANGES file. */
const CHANGES = '/doc/CHANGES';

Expand Down Expand Up @@ -59,6 +68,42 @@ public function __construct(
$this->_directory = $config->getPath();
}

/**
* Update changelog.yml file.
*
* @param string $log The log entry.
* @param array $options Additional options.
*
* @return string Path to the updated changelog.yml file.
*/
public function changelogYml($log, $options)
{
if (!strlen($log)) {
return;
}

if ($changelog = $this->changelogFileExists($this->_directory)) {
if (empty($options['pretend'])) {
$version = $this->addChangelog($log, $this->_directory);
$this->_output->ok(
sprintf(
'Added new note to version %s of %s.',
$version,
$changelog
)
);
} else {
$this->_output->info(
sprintf(
'Would add change log entry to %s now.',
$changelog
)
);
}
return $changelog;
}
}

/**
* Update package.xml file.
*
Expand Down Expand Up @@ -181,8 +226,24 @@ protected function system($call, $options)
}

/**
* Indicates if there is a CHANGES file for this component.
* Indicates if there is a changelog.yml file for this component.
*
* @return string|boolean The path to the changelog.yml file if it exists,
* false otherwise.
*/
public function changelogFileExists()
{
foreach (array(self::CHANGES, self::CHANGES_H5) as $path) {
$changes = $this->_directory . $path;
if (file_exists($changes)) {
return $changes;
}
}
return false;
}

/**
* Indicates if there is a CHANGES file for this component.
*
* @return string|boolean The path to the CHANGES file if it exists, false
* otherwise.
Expand All @@ -198,6 +259,30 @@ public function changesFileExists()
return false;
}

/**
* Add a change log entry to changelog.yml
*
* @param string $entry Change log entry to add.
*
* @returns string The updated version.
*/
public function addChangelog($entry)
{
$hordeInfo = $this->_getHordeInfo($this->_directory);
$changelog = Horde_Yaml::loadFile($this->_directory . self::CHANGELOG);
$version = $hordeInfo['version']['release'];
$info = $changelog[$version];
$notes = explode("\n", trim($info['notes']));
array_unshift($notes, $entry);
$info['notes'] = implode("\n", $notes) . "\n";
$changelog[$version] = $info;
file_put_contents(
$this->_directory . self::CHANGELOG,
Horde_Yaml::dump($changelog, array('wordwrap' => 0))
);
return $version;
}

/**
* Add a change log entry to CHANGES
*
Expand All @@ -223,4 +308,107 @@ public function addChange($entry, $changes)
fclose($newfp);
system("mv -f $tmp $changes");
}

/**
* Updates package.xml from changelog.yml.
*
* @param Horde_Pear_Package_Xml $xml The package xml handler.
* @param string $file Path to the package.xml.
* @param array $options Additional options.
*
* @return string Path to the updated package.xml file.
*/
public function updatePackage($xml, $file, $options)
{
$changelog = $this->changelogFileExists($this->_directory);
if (!$changelog || !file_exists($file)) {
return;
}

if (empty($options['pretend'])) {
$allchanges = Horde_Yaml::loadFile($changelog);
$xml->setNotes($allchanges);
file_put_contents($file, (string)$xml);
$this->_output->ok(sprintf('Updated %s.', $file));
} else {
$this->_output->info(sprintf('Would update %s now.', $file));
}

return $file;
}

/**
* Updates CHANGES from changelog.yml.
*
* @param array $options Additional options.
*
* @return string Path to the updated CHANGES file.
*/
public function updateChanges($options)
{
$changelog = $this->changelogFileExists($this->_directory);
$changes = $this->changesFileExists($this->_directory);
if (!$changelog || !$changes) {
return;
}

$hordeInfo = $this->_getHordeInfo($this->_directory);
$allchanges = Horde_Yaml::loadFile($changelog);

if (empty($options['pretend'])) {
$changesfp = fopen($changes, 'w');
$started = false;

foreach ($allchanges as $version => $info) {
if (!$started && $version != $hordeInfo['version']['release']) {
continue;
}
if (!$started) {
$version .= '-git';
} else {
fwrite($changesfp, "\n\n");
}
$started = true;
$version = 'v' . $version;
$lines = str_repeat('-', strlen($version)) . "\n";
fwrite($changesfp, $lines . $version . "\n" . $lines);

$notes = explode("\n", $info['notes']);
foreach ($notes as $entry) {
$entry = Horde_String::wrap($entry, 79, "\n ");
fwrite($changesfp, "\n" . $entry);
}
}
fclose($changesfp);
$this->_output->ok(
sprintf(
'Updated %s.',
$changes
)
);
} else {
$this->_output->info(
sprintf(
'Would update %s now.',
$changes
)
);
}

return $changes;
}

/**
* Returns the parsed information from the .horde.yml file.
*
* @return array A Horde component information hash.
*/
protected function _getHordeInfo()
{
$path = $this->_directory . self::HORDE_INFO;
if (!file_exists($path)) {
throw new Components_Exception($path . ' not found.');
}
return Horde_Yaml::loadFile($path);
}
}
13 changes: 9 additions & 4 deletions lib/Components/Module/Change.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function getOptionGroupTitle()

public function getOptionGroupDescription()
{
return 'This module records a change log entry in package.xml (and doc/CHANGES in case it exists).';
return 'This module records a change log entry in doc/changelog.yml and package.xml (and doc/CHANGES in case it exists).';
}

public function getOptionGroupOptions()
Expand Down Expand Up @@ -97,8 +97,8 @@ public function getActions()
*/
public function getHelp($action)
{
return 'This module records a change log entry in package.xml and
doc/CHANGES in case it exists.
return 'This module records a change log entry in doc/changelog.yml, package.xml, and
doc/CHANGES in case they exist.
Move into the directory of the component you wish to record a change for
and run
Expand All @@ -112,7 +112,12 @@ public function getHelp($action)
This will use the change log message as commit message. You might wish to
ensure that you already added all changes you want to mark with that
commit message by using "git add ..." before.';
commit message by using "git add ..." before.
If you edited changelog.yml manually you can run the command without an entry
to just update package.xml and doc/CHANGES:
horde-components changed';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Components/Runner/Change.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function run()
if (count($arguments) > 1 && $arguments[0] == 'changed') {
$log = $arguments[1];
} else {
throw new Components_Exception('Please provide a change log entry as additional argument!');
$log = null;
}

if (!empty($options['commit'])) {
Expand Down
4 changes: 4 additions & 0 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,10 @@
<name>Horde_Release</name>
<channel>pear.horde.org</channel>
</package>
<package>
<name>Horde_Yaml</name>
<channel>pear.horde.org</channel>
</package>
</required>
<optional>
<package>
Expand Down

0 comments on commit 04a4b5b

Please sign in to comment.