distromatic/src/changelog.c

308 lines
10 KiB
C

/*
* distromatic - tool for RPM based repositories
*
* Copyright (C) 2004-2020 by Silvan Calarco <silvan.calarco@mambasoft.it>
* Copyright (C) 2006 by Davide Madrisan <davide.madrisan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of version 2 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, to the extent permitted by law; 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, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#if HAVE_STRING_H
# if !STDC_HEADERS && HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#include <string.h>
#include "distromatic.h"
#include "config.h"
#include "changelog.h"
#include "functions.h"
#if !HAVE_STRCHR
# define strchr index
#endif
static struct Packager *firstpackager = NULL;
static struct changeLogFull *firstchangelogfull = NULL;
static struct changeLogFull *currchangelogfull = NULL;
struct Packager *firstPackager() {
return firstpackager;
}
static long packagerListId = 0;
struct Packager *
getPackagerByName(char *name, int create)
{
int i, match=0;
struct Packager *newpackager,
*lastpackager = NULL,
*currpackager = NULL;
if (!name) {
return NULL;
}
currpackager = firstpackager;
while (currpackager && !match) {
if (!strcmp(name, currpackager->name)) match=1;
else {
i=0;
while (currpackager->alias[i] && !match) {
if (!strcmp(name, currpackager->alias[i])) match=1;
i++;
}
}
if (!match) {
lastpackager = currpackager;
currpackager = currpackager->next;
}
}
if (match) {
return currpackager;
}
else if ((!currpackager) && create) {
newpackager = malloc(sizeof(struct Packager));
newpackager->name = (char *) strdup(name);
for (i=0; i<PACKAGER_MAXALIASES; i++) newpackager->alias[i]=NULL;
newpackager->next = NULL;
newpackager->changes_count = 0;
newpackager->packages_count = 0;
newpackager->role = 0;
newpackager->id = ++packagerListId;
if (lastpackager)
lastpackager->next = newpackager;
if (!firstpackager)
firstpackager = newpackager;
return newpackager;
}
return NULL;
}
struct changeLog *
getPackageChangelog(Header h, struct headerSourceList* headersource)
{
int count, i;
struct changeLogFull *newchangelogfull, *prevchangelogfull;
struct changeLog *newchangelog,
*oldchangelog = NULL,
*firstchangelog = NULL;
struct Packager *currpackager = NULL;
char **changelogtext, **changelogrelease;
char *endp;
uint_32 *changelogtime;
char changelogname[255];
changelogtime = headerGetUIntArrayEntry(h, RPMTAG_CHANGELOGTIME, &count);
changelogrelease = headerGetStringArrayEntry(h, RPMTAG_CHANGELOGNAME, &count);
changelogtext = headerGetStringArrayEntry(h, RPMTAG_CHANGELOGTEXT, &count);
for (i = 0; i < count; i++) {
newchangelog = malloc(sizeof(struct changeLog));
if (oldchangelog) {
oldchangelog->next = newchangelog;
}
newchangelog->time = changelogtime[i];
strcpy(changelogname, changelogrelease[i]);
endp = strchr(changelogname, '>');
if (endp) {
endp[1] = '\0';
}
changelogrelease[i] = strrchr(changelogrelease[i], ' ')+1;
newchangelog->release = changelogrelease[i];
if ((currpackager = getPackagerByName(changelogname, 1))) {
newchangelog->pkg = currpackager;
} else {
newchangelog->pkg = NULL;
}
if (changelogtext[i]) {
newchangelog->text = (char *) strdup(changelogtext[i]);
} else {
newchangelog->text = NULL;
}
newchangelog->next = NULL;
if (!firstchangelog) {
firstchangelog = newchangelog;
}
oldchangelog = newchangelog;
newchangelogfull = malloc(sizeof(struct changeLogFull));
newchangelogfull->changelog = newchangelog;
newchangelogfull->source = headersource;
newchangelogfull->next = NULL;
currchangelogfull = firstchangelogfull;
prevchangelogfull = NULL;
while (currchangelogfull &&
(currchangelogfull->changelog->time > newchangelogfull->changelog->time)) {
prevchangelogfull = currchangelogfull;
currchangelogfull = currchangelogfull->next;
}
if(prevchangelogfull) {
prevchangelogfull->next = newchangelogfull;
} else {
firstchangelogfull = newchangelogfull;
}
newchangelogfull->next = currchangelogfull;
}
headersource->changelog = firstchangelog;
return firstchangelog;
}
char *changeLogTimeStr(char buf[16], struct changeLog *changelog)
{
struct tm *changelogtime;
changelogtime = localtime((time_t *) & changelog->time);
strftime((char *) buf, 16, "%a %h %d %Y", changelogtime);
return buf;
}
int
printChangelogSince(FILE *fout, struct configTag *ct,
struct tm *sincetime, int html)
{
struct changeLogFull *changelogfull;
char strdate[16];
char buffer[PATH_MAX];
struct Packager *currpackager = firstpackager;
time_t simpletime = mktime(sincetime), lasttime = 0;
strftime((char *) &strdate, 16, "%a %h %d %Y", sincetime);
if (!html) {
fprintf(fout,"\nPackagers statistics (changelog since %s):\n\n",
(char *) &strdate);
/* FIXME: `packages_count' is never incremented, so its value is `0' */
fprintf(fout,"Summary (name, packages, updates)\n");
fprintf(fout,"---------------------------------\n");
while (currpackager) {
fprintf(fout,"%s %d, %d\n",
strcmp(currpackager->name, "") ?
currpackager->name : "(noname)",
currpackager->packages_count,
currpackager->changes_count);
currpackager = currpackager->next;
}
fprintf(fout,"\nDetails\n-------");
}
changelogfull = firstchangelogfull;
while (changelogfull) {
if ((changelogfull->changelog->time >= simpletime) &&
(changelogfull->source->altrepository == ct->repository_level)) {
if (!html) {
fprintf(fout,"\n[%s %s] ",
changelogfull->source->name,
changelogfull->changelog->release);
fprintf(fout,"%s %s\n%s\n",
changeLogTimeStr(strdate, changelogfull->changelog),
strcmp(changelogfull->changelog->pkg->name, "") ?
changelogfull->changelog->pkg->name : "(noname)",
changelogfull->changelog->text);
} else {
if (changelogfull->changelog->time != lasttime) {
if (lasttime) fprintf(fout,"<hr>");
fprintf(fout,"<p><h2>%s</h2>",
changeLogTimeStr(strdate, changelogfull->changelog));
lasttime=changelogfull->changelog->time;
}
fprintf(fout,"<p><a href=\"%stag=%s&amp;pkg=%s.source\">%s</a> %s - ",
ct->configdefaults->url_prefix,
ct->tag,
changelogfull->source->name,
changelogfull->source->name,
changelogfull->changelog->release);
if (strcmp(changelogfull->changelog->pkg->name, "")) {
if ((changelogfull->changelog->pkg->role & PACKAGER_ROLE_MAINTAINER) &&
(changelogfull->changelog->pkg->packages_count)) {
fprintf(fout,"<a href=\"%stag=%s&amp;maintainer=%s\">%s</a>",
ct->configdefaults->url_prefix,
ct->tag,
changelogfull->changelog->pkg->name,
changelogfull->changelog->pkg->name);
} else {
fprintf(fout,"%s",changelogfull->changelog->pkg->name);
}
} else {
fprintf(fout,"(noname)");
}
fprintf(fout,"<br>%s<br>\n",
htmlclean(changelogfull->changelog->text,buffer,PATH_MAX));
}
}
changelogfull = changelogfull->next;
// pkgchanged = 0;
// headersourcelist = headersourcelist->next;
}
fprintf(fout,"\n");
return 0;
}
int
printChangelog(struct changeLog *changelog)
{
printf("Changelog:\n");
while (changelog) {
char strdate[16];
changeLogTimeStr(strdate, changelog),
printf("%s - %s\n%s\n",
changeLogTimeStr(strdate, changelog),
changelog->pkg->name ? changelog->pkg->name : "(noname)",
changelog->text);
changelog = changelog->next;
}
return 0;
}