Commit ab2ecbdf authored by Bernhard Link's avatar Bernhard Link

Add a magic - update rule to downgrade or remove packages no longer found in the upstream mirror

parent 075e52b7
2004-12-30 Bernhard R. Link <brlink@debian.org>
* Tidy up (introduce bool_t and replace dpkgversion_isNewer)
* add a magic rule minus ("-") to mark all packages to be
deleted.
* add a checkupdate command to show what would be done.
2004-12-24 Bernhard R. Link <brlink@debian.org>
* Fixed a boolean inversion in the check if | is allowed
in formulas.
......
......@@ -121,6 +121,11 @@ description of
.B conf/updates
below.
.TP
.BR checkupdate " [ " \fIcodenames\fP " ]"
Same like
.B update,
but will show what it will change instead of actually changing it.
.TP
.B includedeb \fIcodename\fP \fI.deb-filename\fP
Include the given binary Debian package (.deb) in the specified
distribution, applying override information and guessing all
......@@ -277,8 +282,9 @@ Components with a debian\-installer subhirachy containing .udebs.
(E.g. simply "main")
.TP
.B Update
When this field is present, it describes which update rules apply
for this distribution.
When this field is present, it describes which update rules are used
for this distribution. There also can be a magic rule minus ("\-"),
see below.
.TP
.B SignWith
When this field is present, a Relese.gpg file will be generated.
......@@ -428,6 +434,55 @@ Things like
.B md5sum
The checksum of a file, beeing in the format
"\fI<md5sum of file>\fP \fI<length of file>\fP"
.SH Some note on updates
.SS A version is not overwritten with the same version.
.B reprepro
will never update a package with a version it already has. This would
be equivalent to rebuilding the whole database with every single upgrade.
To force the new same version in, remove it and then update. (If you
do no
.B deleteunreferenced
inbetween, it will not need to reget the
Packages files themselves. If those change, better to a
.B deleteunreferenced
in between or a
.B __forget
on the specific files.
.SS The magic delete rule ("\-").
A minus as a single word in the
.B Updates:
line of an distribution marks everything to be deleted. The mark causes later rules
to get packages even if they have (strict) lower versions. The mark will
get removed if a later rule sets the package on hold (hold is not yet implemented,
in case you might wonder) or would get a package with the same version
(Which it will not, see above). If the mark is still there at the end of the processing,
the package will get removed.
.P
Thus the line "Updates: -
.I rules
" will cause all packages to be exactly the
highest Version found in
.I rules.
The line "Updates:
.I near
-
.I rules
" will do the same, except if it needs to download packages, it might download
it from
.I near
except when too confused. (It will get too confused e.g. when
.I near
or
.I rules
have multiple versions of the package and the highest in
.I near
is not the first one in
.I rules,
as it never remember more than one possible spring for a package.
.P
Warning: This rule applies to all type/component/architecture tripples
of a distribution, not only those some other update rule applies to.
(That means it will delete everthing in those!)
.SH BUGS
The
.B \-\-force
......
......@@ -615,7 +615,7 @@ static int action_update(int argc,const char *argv[]) {
return EXIT_RET(result);
}
result = updates_update(dbdir,listdir,methoddir,files,refs,distributions,force);
result = updates_update(dbdir,methoddir,files,refs,distributions,force);
r = files_done(files);
RET_ENDUPDATE(result,r);
......@@ -641,6 +641,49 @@ static int action_update(int argc,const char *argv[]) {
return EXIT_RET(result);
}
static int action_checkupdate(int argc,const char *argv[]) {
retvalue result;
struct update_pattern *patterns;
struct distribution *distributions;
if( argc < 1 ) {
fprintf(stderr,"reprepro checkupdate [<distributions>]\n");
return EXIT_FAILURE;
}
result = dirs_make_recursive(listdir);
if( RET_WAS_ERROR(result) ) {
return EXIT_RET(result);
}
result = distribution_getmatched(confdir,argc-1,argv+1,&distributions);
if( RET_WAS_ERROR(result) )
return EXIT_RET(result);
if( result == RET_NOTHING ) {
fprintf(stderr,"Nothing to do found!\n");
return EXIT_RET(RET_NOTHING);
}
result = updates_getpatterns(confdir,&patterns,0);
if( RET_WAS_ERROR(result) )
return EXIT_RET(result);
result = updates_getindices(listdir,patterns,distributions);
if( RET_WAS_ERROR(result) )
return EXIT_RET(result);
result = updates_checkupdate(dbdir,methoddir,distributions,force);
while( distributions ) {
struct distribution *d = distributions->next;
distribution_free(distributions);
distributions = d;
}
return EXIT_RET(result);
}
/***********************rereferencing*************************/
struct data_binsrcreref { const struct distribution *distribution; DB *references;};
......@@ -992,6 +1035,7 @@ static struct action {
{"dumpunreferenced", action_dumpunreferenced},
{"deleteunreferenced", action_deleteunreferenced},
{"update", action_update},
{"checkupdate", action_checkupdate},
{"includedeb", action_includedeb},
{"includedsc", action_includedsc},
{"include", action_include},
......
This diff is collapsed.
......@@ -28,6 +28,7 @@ retvalue updates_getindices(const char *listdir,const struct update_pattern *pat
// retvalue updates_queuelists(struct aptmethodrun *run,struct distribution *distribution,int force);
// retvalue updates_readindices(const char *dbdir,struct downloadcache *cache,filesdb filesdb,struct distribution *distribution,int force);
retvalue updates_update(const char *dbdir,const char *listdir,const char *methoddir,filesdb filesdb,DB *refsdb,struct distribution *distributions,int force);
retvalue updates_update(const char *dbdir,const char *methoddir,filesdb filesdb,DB *refsdb,struct distribution *distributions,int force);
retvalue updates_checkupdate(const char *dbdir,const char *methoddir,struct distribution *distributions,int force);
#endif
......@@ -43,6 +43,11 @@ struct package_data {
* (either is version_in_use or version_new)*/
const char *version;
/* if this is != 0, package will be deleted afterwards,
* (or new version simply ignored if it is not yet in the
* archive) */
bool_t deleted;
/* The most recent version we found upstream:
* NULL means nothing found. */
char *new_version;
......@@ -50,7 +55,7 @@ struct package_data {
struct aptmethod *aptmethod;
/* the new control-chunk for the package to go in
* non-NULL if new_version && newversion > version_in_use */
* non-NULL if new_version && newversion == version_in_use */
char *new_control;
/* the list of files that will belong to this:
* same validity */
......@@ -156,6 +161,7 @@ retvalue upgradelist_initialize(struct upgradelist **ul,struct target *t,const c
return r;
}
/* Beginn with the packages currently in the archive */
r = packages_foreach(t->packages,save_package_version,upgrade,0);
r2 = target_closepackagesdb(t);
RET_UPDATE(r,r2);
......@@ -292,6 +298,7 @@ static retvalue upgradelist_trypackage(void *data,const char *chunk){
return RET_ERROR_OOM;
}
assert(upgrade->currentaptmethod);
new->deleted = FALSE; //to be sure...
new->aptmethod = upgrade->currentaptmethod;
new->name = packagename;
packagename = NULL; //to be sure...
......@@ -324,7 +331,7 @@ static retvalue upgradelist_trypackage(void *data,const char *chunk){
free(version);
return r;
}
if( versioncmp <= 0 ) {
if( versioncmp <= 0 && !current->deleted ) {
/* there already is a newer version, so
* doing nothing but perhaps updating what
* versions are around, when we are newer
......@@ -347,7 +354,7 @@ static retvalue upgradelist_trypackage(void *data,const char *chunk){
free(packagename);
return RET_NOTHING;
}
if( verbose > 30 )
if( versioncmp > 0 && verbose > 30 )
fprintf(stderr,"'%s' from '%s' is newer than '%s' currently\n",
version,packagename,current->version);
decision = upgrade->predecide(upgrade->predecide_data,current->name,
......@@ -356,18 +363,53 @@ static retvalue upgradelist_trypackage(void *data,const char *chunk){
decision = upgrade->decide(upgrade->decide_data,current->name,
current->version,version,chunk);
if( decision != UD_UPGRADE ) {
//TODO: perhaps set a flag if hold was applied...
/* Even if we do not install it, setting it on hold
* will keep it or even install from a mirror before
* the delete was applied */
if( decision == UD_HOLD )
current->deleted = FALSE;
free(version);
free(packagename);
return RET_NOTHING;
}
if( versioncmp == 0 ) {
/* we are replacing a package with the same version,
* so we keep the old one for sake of speed. */
// TODO: add switch to force reimport of everything...
current->deleted = FALSE;
free(version);
free(packagename);
return RET_NOTHING;
}
if( versioncmp <= 0 && current->version == current->new_version
&& current->version_in_use != NULL ) {
/* The version to include is less than the newest
* version we found, but it is also not the same like
* the version we already have? */
int vcmp = 1;
(void)dpkgversions_cmp(version,current->version_in_use,&vcmp);
if( vcmp == 0 ) {
current->deleted = FALSE;
current->version = current->version_in_use;
free(version);
free(packagename);
return RET_NOTHING;
}
}
// TODO: the following case might be worth considering, but sadly new_version
// might have changed without the proper data set.
// if( versioncmp >= 0 && current->version == current->version_in_use
// && current->new_version != NULL ) {
r = upgrade->target->getinstalldata(upgrade->target,packagename,version,chunk,&control,&files,&md5sums,&origfiles);
free(packagename);
if( RET_WAS_ERROR(r) ) {
free(version);
return r;
}
current->deleted = FALSE;
free(current->new_version);
current->new_version = version;
current->version = version;
......@@ -392,17 +434,26 @@ retvalue upgradelist_update(struct upgradelist *upgrade,struct aptmethod *method
return chunk_foreach(filename,upgradelist_trypackage,upgrade,force,FALSE);
}
/* mark all packages as deleted, so they will vanis unless readded or reholded */
retvalue upgradelist_deleteall(struct upgradelist *upgrade) {
struct package_data *pkg;
for( pkg = upgrade->list ; pkg ; pkg = pkg->next ) {
pkg->deleted = TRUE;
}
return RET_OK;
}
retvalue upgradelist_listmissing(struct upgradelist *upgrade,filesdb files){
struct package_data *pkg;
pkg = upgrade->list;
while( pkg ) {
for( pkg = upgrade->list ; pkg ; pkg = pkg->next ) {
if( pkg->version == pkg->new_version ) {
files_printmissing(files,&pkg->new_filekeys,&pkg->new_md5sums,&pkg->new_origfiles);
}
pkg = pkg->next;
}
return RET_OK;
}
......@@ -411,10 +462,9 @@ retvalue upgradelist_listmissing(struct upgradelist *upgrade,filesdb files){
retvalue upgradelist_enqueue(struct upgradelist *upgrade,struct downloadcache *cache,filesdb filesdb,int force) {
struct package_data *pkg;
retvalue result,r;
pkg = upgrade->list;
result = RET_NOTHING;
while( pkg ) {
if( pkg->version == pkg->new_version ) {
for( pkg = upgrade->list ; pkg ; pkg = pkg->next ) {
if( pkg->version == pkg->new_version && !pkg->deleted) {
assert(pkg->aptmethod);
r = downloadcache_addfiles(cache,filesdb,pkg->aptmethod,
&pkg->new_origfiles,
......@@ -424,7 +474,6 @@ retvalue upgradelist_enqueue(struct upgradelist *upgrade,struct downloadcache *c
if( RET_WAS_ERROR(r) && !force )
break;
}
pkg = pkg->next;
}
return result;
}
......@@ -439,9 +488,8 @@ retvalue upgradelist_install(struct upgradelist *upgrade,const char *dbdir,files
result = target_initpackagesdb(upgrade->target,dbdir);
if( RET_WAS_ERROR(result) )
return result;
pkg = upgrade->list;
while( pkg ) {
if( pkg->version == pkg->new_version ) {
for( pkg = upgrade->list ; pkg ; pkg = pkg->next ) {
if( pkg->version == pkg->new_version && !pkg->deleted ) {
r = files_expectfiles(files,&pkg->new_filekeys,
&pkg->new_md5sums);
if( ! RET_WAS_ERROR(r) )
......@@ -454,51 +502,70 @@ retvalue upgradelist_install(struct upgradelist *upgrade,const char *dbdir,files
if( RET_WAS_ERROR(r) && !force )
break;
}
pkg = pkg->next;
if( pkg->deleted && pkg->version_in_use != NULL ) {
// TODO: what if there were previous errors,
// prevent removal of packages here?
r = target_removepackage(upgrade->target,references,pkg->name);
RET_UPDATE(result,r);
if( RET_WAS_ERROR(r) && !force )
break;
}
}
r = target_closepackagesdb(upgrade->target);
RET_ENDUPDATE(result,r);
return result;
}
retvalue upgradelist_dump(struct upgradelist *upgrade){
void upgradelist_dump(struct upgradelist *upgrade){
struct package_data *pkg;
pkg = upgrade->list;
while( pkg ) {
if( pkg->version == pkg->version_in_use ) {
if( pkg->new_version ) {
if( verbose > 1 )
printf("'%s': '%s' will be kept "
"(best new: '%s')\n",
for( pkg = upgrade->list ; pkg ; pkg = pkg->next ) {
if( pkg->deleted ) {
if( pkg->version_in_use && pkg->new_version ) {
printf("'%s': '%s' will be deleted"
" (best new: '%s')\n",
pkg->name,pkg->version_in_use,
pkg->new_version);
} else if( pkg->version_in_use ) {
printf("'%s': '%s' will be deleted"
" (no longer available)\n",
pkg->name,pkg->version_in_use);
} else {
if( verbose > 0 )
printf("'%s': '%s' will be kept "
"(unavailable for reload)\n",
pkg->name,pkg->version_in_use);
printf("'%s': will NOT be added as '%s'\n",
pkg->name,pkg->new_version);
}
} else {
if( pkg->version_in_use )
printf("'%s': '%s' will be upgraded to '%s':\n "
"files needed: ",
pkg->name,pkg->version_in_use,
pkg->new_version);
else
printf("'%s': newly installed as '%s':\n"
"files needed: ",
pkg->name, pkg->new_version);
strlist_fprint(stdout,&pkg->new_filekeys);
printf("\nwith md5sums: ");
strlist_fprint(stdout,&pkg->new_md5sums);
printf("\ninstalling as: '%s'\n",pkg->new_control);
}
if( pkg->version == pkg->version_in_use ) {
if( pkg->new_version ) {
if( verbose > 1 )
printf("'%s': '%s' will be kept"
" (best new: '%s')\n",
pkg->name,pkg->version_in_use,
pkg->new_version);
} else {
if( verbose > 0 )
printf("'%s': '%s' will be kept"
" (unavailable for reload)\n",
pkg->name,pkg->version_in_use);
}
pkg = pkg->next;
} else {
if( pkg->version_in_use )
printf("'%s': '%s' will be upgraded"
" to '%s':\n files needed: ",
pkg->name,pkg->version_in_use,
pkg->new_version);
else
printf("'%s': newly installed"
" as '%s':\n files needed: ",
pkg->name, pkg->new_version);
strlist_fprint(stdout,&pkg->new_filekeys);
printf("\nwith md5sums: ");
strlist_fprint(stdout,&pkg->new_md5sums);
printf("\ninstalling as: '%s'\n",pkg->new_control);
}
}
}
return RET_OK;
}
/* standard answer function */
......
......@@ -27,12 +27,15 @@ struct upgradelist;
retvalue upgradelist_initialize(struct upgradelist **ul,struct target *target,const char *dbdir,upgrade_decide_function *decide,void *decide_data);
retvalue upgradelist_free(struct upgradelist *upgrade);
retvalue upgradelist_dump(struct upgradelist *upgrade);
void upgradelist_dump(struct upgradelist *upgrade);
retvalue upgradelist_listmissing(struct upgradelist *upgrade,filesdb files);
/* Take all items in 'filename' into account, and remember them coming from 'method' */
retvalue upgradelist_update(struct upgradelist *upgrade,struct aptmethod *method,const char *filename,upgrade_decide_function *predecide,void *decide_data,int force);
/* mark all packages as deleted, so they will vanis unless readded or reholded */
retvalue upgradelist_deleteall(struct upgradelist *upgrade);
//TODO add a function to reduce data-load by removing anything not needed
//any longer. (perhaps with a flag to remove all packages that are no
//longer available upstream)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment