[pacman-dev] [PATCH] Save backup files with extension .pacsave.timestamp
Teach pacman to save backup files using extension of .pacsave.timestamp "timestamp" is the time of removal of the backup file. It is in <year>-<month>-<day>-<HHMMSS> format, where: - year is either the year with century or a 2 digit number from 00 to 99 (year without century) if the timestamp string exceeds 20 characters - month is a 2 digit number from 01 to 12 - day is a 2 digit number from 01 to 31 - HH is a 2 digit number from 00 to 23 representing the hour - MM and SS are 2 digit numbers from 00 to 59 representing minutes and seconds respectively An example of such a pacsave file is /etc/pacman.conf.pacsave.2011-07-29-145035 This addresses FS#24192 (pacman overwrites .pacsave files) FILE_PACSAVE rule for the test suite is updated to reflect the change in .pacsave file extension. FILE_PACSAVE rules can be used as per before this patch. Signed-off-by: Pang Yan Han <pangyanhan@gmail.com> --- doc/pacman.8.txt | 13 ++++++++++++- lib/libalpm/remove.c | 20 ++++++++++++++++++-- test/pacman/pmrule.py | 21 +++++++++++++++++++-- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 64b1ff3..d029294 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -54,8 +54,19 @@ Operations removed, in which case every package in that group will be removed. Files belonging to the specified package will be deleted, and the database will be updated. Most configuration files will be saved - with a '.pacsave' extension unless the '\--nosave' option is used. + with a '.pacsave-<timestamp>' extension unless the '\--nosave' option is used. See <<RO,Remove Options>> below. ++ +'<timestamp>' is the time of removal of the configuration file. It is in +<year>-<month>-<day>-<HHMMSS> format, where: ++ + - year is either the year with century or a 2 digit number from 00 to 99 + (year without century) if the string exceeds 20 characters + - month is a 2 digit number from 01 to 12 + - day is a 2 digit number from 01 to 31 + - HH is a 2 digit number from 00 to 23 representing the hour + - MM and SS are 2 digit numbers from 00 to 59 representing minutes and seconds + respectively *-S, \--sync*:: Synchronize packages. Packages are installed directly from the ftp diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 83c437f..a39a154 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <errno.h> #include <string.h> +#include <time.h> #include <limits.h> #include <unistd.h> #include <sys/stat.h> @@ -287,7 +288,8 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, } } } else { - /* if the file needs backup and has been modified, back it up to .pacsave */ + /* if the file needs backup and has been modified, back it up to + * .pacsave.YYYY-MM-DD-HHMMSS */ alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info); if(backup) { if(nosave) { @@ -298,7 +300,21 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, FREE(filehash); if(cmp != 0) { char newpath[PATH_MAX]; - snprintf(newpath, PATH_MAX, "%s.pacsave", file); + char timestr[21]; + time_t curtime; + struct tm tm; + size_t ret; + + curtime = time(NULL); + localtime_r(&curtime, &tm); + ret = strftime(timestr, 21, "%Y-%m-%d-%H%M%S", &tm); + if (ret == 0) { + /* Year with century can't fit. + * So we print year without century (00 to 99) */ + strftime(timestr, 21, "%y-%m-%d-%H%M%S", &tm); + } + + snprintf(newpath, PATH_MAX, "%s.pacsave.%s", file, timestr); rename(file, newpath); _alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), file, newpath); alpm_logaction(handle, "warning: %s saved as %s\n", file, newpath); diff --git a/test/pacman/pmrule.py b/test/pacman/pmrule.py index cb7ae88..44cee8a 100644 --- a/test/pacman/pmrule.py +++ b/test/pacman/pmrule.py @@ -17,6 +17,7 @@ import os import stat +import re import util @@ -141,8 +142,24 @@ def check(self, test): if not os.path.isfile("%s.pacorig" % filename): success = 0 elif case == "PACSAVE": - if not os.path.isfile("%s.pacsave" % filename): - success = 0 + # pacsave.YYYY-MM-DD-HHMMSS + saved_re = re.compile(filename + ".pacsave." + "\d{2,}-\d{2}-\d{2}-\d{6}") + + # Extract directory component of pacsave file + dir_ = "" + dir_re = re.compile('(.*)/[^/]*') + dir_match = dir_re.match(filename) + if dir_match is not None: + dir_ = dir_match.group(1) + dir_ = os.path.join(test.root, dir_) + + success = 0 + files = os.listdir(dir_) + for f in files: + fullname = os.path.join(dir_, f) + if saved_re.match(fullname): + success = 1 + break else: print "FILE rule '%s' not found" % case success = -1 -- 1.7.6.178.g55272
On Fri, Jul 29, 2011 at 2:03 AM, Pang Yan Han <pangyanhan@gmail.com> wrote:
Teach pacman to save backup files using extension of .pacsave.timestamp "timestamp" is the time of removal of the backup file. It is in <year>-<month>-<day>-<HHMMSS> format, where:
- year is either the year with century or a 2 digit number from 00 to 99 (year without century) if the timestamp string exceeds 20 characters Already too odd to me. There is zero reason to not always do YYYY-MM-DD_HH:MM:SS format IMO, which also makes this whole explanation unnecessary as it will be recognized as a standard format.
Is the HH:MM:SS bit really necessary? Perhaps a format such as that like logrotate would work. Given 99% of the time you wouldn't have more than one file on a given day, stick with foo.pacsave.2011-08-02, then the next would become something like foo.pacsave.2011-08-02.1, .2, etc. As I'm thinking as I'm typing and drinking my morning coffee here, why even do the date at all? Why not just check for the presence of an existing pacsave file and rotate them down to .1, .2, etc. just like logrotate would? This is what the feature request asks for, and double-timestamping a file just seems confusing.
- month is a 2 digit number from 01 to 12 - day is a 2 digit number from 01 to 31 - HH is a 2 digit number from 00 to 23 representing the hour - MM and SS are 2 digit numbers from 00 to 59 representing minutes and seconds respectively
An example of such a pacsave file is /etc/pacman.conf.pacsave.2011-07-29-145035
This addresses FS#24192 (pacman overwrites .pacsave files)
FILE_PACSAVE rule for the test suite is updated to reflect the change in .pacsave file extension. FILE_PACSAVE rules can be used as per before this patch.
Signed-off-by: Pang Yan Han <pangyanhan@gmail.com> --- doc/pacman.8.txt | 13 ++++++++++++- lib/libalpm/remove.c | 20 ++++++++++++++++++-- test/pacman/pmrule.py | 21 +++++++++++++++++++-- 3 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 64b1ff3..d029294 100644 --- a/doc/pacman.8.txt +++ b/doc/pacman.8.txt @@ -54,8 +54,19 @@ Operations removed, in which case every package in that group will be removed. Files belonging to the specified package will be deleted, and the database will be updated. Most configuration files will be saved - with a '.pacsave' extension unless the '\--nosave' option is used. + with a '.pacsave-<timestamp>' extension unless the '\--nosave' option is used. See <<RO,Remove Options>> below. ++ +'<timestamp>' is the time of removal of the configuration file. It is in +<year>-<month>-<day>-<HHMMSS> format, where: ++ + - year is either the year with century or a 2 digit number from 00 to 99 + (year without century) if the string exceeds 20 characters + - month is a 2 digit number from 01 to 12 + - day is a 2 digit number from 01 to 31 + - HH is a 2 digit number from 00 to 23 representing the hour + - MM and SS are 2 digit numbers from 00 to 59 representing minutes and seconds + respectively
*-S, \--sync*:: Synchronize packages. Packages are installed directly from the ftp diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c index 83c437f..a39a154 100644 --- a/lib/libalpm/remove.c +++ b/lib/libalpm/remove.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <errno.h> #include <string.h> +#include <time.h> #include <limits.h> #include <unistd.h> #include <sys/stat.h> @@ -287,7 +288,8 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, } } } else { - /* if the file needs backup and has been modified, back it up to .pacsave */ + /* if the file needs backup and has been modified, back it up to + * .pacsave.YYYY-MM-DD-HHMMSS */ alpm_backup_t *backup = _alpm_needbackup(fileobj->name, info); if(backup) { if(nosave) { @@ -298,7 +300,21 @@ static void unlink_file(alpm_handle_t *handle, alpm_pkg_t *info, FREE(filehash); if(cmp != 0) { char newpath[PATH_MAX]; - snprintf(newpath, PATH_MAX, "%s.pacsave", file); + char timestr[21]; + time_t curtime; + struct tm tm; + size_t ret; + + curtime = time(NULL); + localtime_r(&curtime, &tm); + ret = strftime(timestr, 21, "%Y-%m-%d-%H%M%S", &tm); + if (ret == 0) { + /* Year with century can't fit. + * So we print year without century (00 to 99) */ + strftime(timestr, 21, "%y-%m-%d-%H%M%S", &tm); + } + + snprintf(newpath, PATH_MAX, "%s.pacsave.%s", file, timestr); rename(file, newpath); _alpm_log(handle, ALPM_LOG_WARNING, _("%s saved as %s\n"), file, newpath); alpm_logaction(handle, "warning: %s saved as %s\n", file, newpath); diff --git a/test/pacman/pmrule.py b/test/pacman/pmrule.py index cb7ae88..44cee8a 100644 --- a/test/pacman/pmrule.py +++ b/test/pacman/pmrule.py @@ -17,6 +17,7 @@
import os import stat +import re
import util
@@ -141,8 +142,24 @@ def check(self, test): if not os.path.isfile("%s.pacorig" % filename): success = 0 elif case == "PACSAVE": - if not os.path.isfile("%s.pacsave" % filename): - success = 0 + # pacsave.YYYY-MM-DD-HHMMSS + saved_re = re.compile(filename + ".pacsave." + "\d{2,}-\d{2}-\d{2}-\d{6}") + + # Extract directory component of pacsave file + dir_ = "" + dir_re = re.compile('(.*)/[^/]*') + dir_match = dir_re.match(filename) + if dir_match is not None: + dir_ = dir_match.group(1) + dir_ = os.path.join(test.root, dir_) + + success = 0 + files = os.listdir(dir_) + for f in files: + fullname = os.path.join(dir_, f) + if saved_re.match(fullname): + success = 1 + break else: print "FILE rule '%s' not found" % case success = -1 -- 1.7.6.178.g55272
participants (2)
-
Dan McGee
-
Pang Yan Han