Fix bug #9554: When we save a file that was not originally in the current

LyX format, create a backup of the original file. We put it in the backup
directory, if one exists, otherwise in the directory the original file is
in. This is the same strategy as for normal backups. Basically, the only
diferences are: (i) what name we use and (ii) we do not over-write any
backups that may already exist.
This commit is contained in:
Richard Heck 2015-11-10 12:39:24 -05:00
parent 9894e0be23
commit cc83dfa887
2 changed files with 81 additions and 14 deletions

View File

@ -204,6 +204,13 @@ public:
*/
bool file_fully_loaded;
/// original format of loaded file
int file_format;
/// if the file was originally loaded from an older format, do
/// we need to back it up still?
bool need_format_backup;
/// Ignore the parent (e.g. when exporting a child standalone)?
bool ignore_parent;
@ -405,11 +412,11 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_,
Buffer const * cloned_buffer)
: owner_(owner), lyx_clean(true), bak_clean(true), unnamed(false),
internal_buffer(false), read_only(readonly_), filename(file),
file_fully_loaded(false), ignore_parent(false), toc_backend(owner),
macro_lock(false), timestamp_(0), checksum_(0), wa_(0), gui_(0),
undo_(*owner), bibinfo_cache_valid_(false), bibfile_cache_valid_(false),
cite_labels_valid_(false), inset(0), preview_loader_(0),
cloned_buffer_(cloned_buffer), clone_list_(0),
file_fully_loaded(false), file_format(LYX_FORMAT), need_format_backup(false),
ignore_parent(false), toc_backend(owner), macro_lock(false), timestamp_(0),
checksum_(0), wa_(0), gui_(0), undo_(*owner), bibinfo_cache_valid_(false),
bibfile_cache_valid_(false), cite_labels_valid_(false), inset(0),
preview_loader_(0), cloned_buffer_(cloned_buffer), clone_list_(0),
doing_export(false), parent_buffer(0),
word_count_(0), char_count_(0), blank_count_(0)
{
@ -1132,10 +1139,15 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn)
if (file_format != LYX_FORMAT) {
FileName tmpFile;
ReadStatus const ret_clf = convertLyXFormat(fn, tmpFile, file_format);
ReadStatus ret_clf = convertLyXFormat(fn, tmpFile, file_format);
if (ret_clf != ReadSuccess)
return ret_clf;
return readFile(tmpFile);
ret_clf = readFile(tmpFile);
if (ret_clf == ReadSuccess) {
d->file_format = file_format;
d->need_format_backup = true;
}
return ret_clf;
}
// FIXME: InsetInfo needs to know whether the file is under VCS
@ -1294,6 +1306,41 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
}
string Buffer::getBackupName() const {
FileName const & fn = fileName();
string const fname = fn.onlyFileNameWithoutExt();
string const fext = fn.extension();
string const fpath = lyxrc.backupdir_path.empty() ?
fn.onlyPath().absFileName() :
lyxrc.backupdir_path;
string const fform = convert<string>(d->file_format);
string const backname = fname + "-" + fform;
FileName backup(addName(fpath, addExtension(backname, fext)));
// limit recursion, just in case
int v = 1;
unsigned long orig_checksum = 0;
while (backup.exists() && v < 100) {
if (orig_checksum == 0)
orig_checksum = fn.checksum();
unsigned long new_checksum = backup.checksum();
if (orig_checksum == new_checksum) {
LYXERR(Debug::FILES, "Not backing up " << fn <<
"since " << backup << "has the same checksum.");
// a bit of a hack, but we have to check this anyway
// below, and setting this is simpler than introducing
// a special boolean for this purpose.
v = 1000;
break;
}
string newbackname = backname + "-" + convert<string>(v);
backup.set(addName(fpath, addExtension(newbackname, fext)));
v++;
}
return v < 100 ? backup.onlyFileName() : "";
}
// Should probably be moved to somewhere else: BufferView? GuiView?
bool Buffer::save() const
{
@ -1353,13 +1400,24 @@ bool Buffer::save() const
// we will set this to false if we fail
bool made_backup = true;
FileName backupName(absFileName() + '~');
if (lyxrc.make_backup) {
FileName backupName;
if (lyxrc.make_backup || d->need_format_backup) {
if (d->need_format_backup) {
string backup_name = getBackupName();
if (!backup_name.empty())
backupName.set(backup_name);
}
// If we for some reason failed to find a backup name in case of
// a format change, this will still set one. It's the best we can
// do in this case.
if (backupName.empty()) {
backupName.set(fileName().absFileName() + "~");
if (!lyxrc.backupdir_path.empty()) {
string const mangledName =
subst(subst(backupName.absFileName(), '/', '!'), ':', '!');
backupName = FileName(addName(lyxrc.backupdir_path,
mangledName));
backupName.set(addName(lyxrc.backupdir_path, mangledName));
}
}
LYXERR(Debug::FILES, "Backing up original file to " <<
@ -1376,6 +1434,10 @@ bool Buffer::save() const
"Please check whether the directory exists and is writable."),
from_utf8(backupName.absFileName())));
//LYXERR(Debug::DEBUG, "Fs error: " << fe.what());
} else if (d->need_format_backup) {
// the original file has been backed up successfully, so we
// will not need to do that again
d->need_format_backup = false;
}
}
@ -1392,6 +1454,9 @@ bool Buffer::save() const
// time stamp is invalidated by copying/moving
saveCheckSum();
markClean();
if (d->file_format != LYX_FORMAT)
// the file associated with this buffer is now in the current format
d->file_format = LYX_FORMAT;
return true;
}
// else we saved the file, but failed to move it to the right location.

View File

@ -267,6 +267,8 @@ private:
/// of the temporary file to be read
ReadStatus convertLyXFormat(support::FileName const & fn,
support::FileName & tmpfile, int from_format);
/// get appropriate name for backing up files from older versions
std::string getBackupName() const;
//@}
public: