fix for [#27410] Manual save kills actual .blend file if disk space is low
- moved do_history into WM_write_file after successful write of .blend@ temporary file - Added new file flag, to avoid writing history on writing the startup.blend, autosave files and undo. Thanks Campbell, Brecht for review!
This commit is contained in:
@@ -145,6 +145,7 @@ typedef struct Global {
|
||||
#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */
|
||||
#define G_FILE_RECOVER (1 << 23)
|
||||
#define G_FILE_RELATIVE_REMAP (1 << 24)
|
||||
#define G_FILE_HISTORY (1 << 25)
|
||||
|
||||
/* G.windowstate */
|
||||
#define G_WINDOWSTATE_USERDEF 0
|
||||
|
||||
@@ -523,7 +523,8 @@ void BKE_write_undo(bContext *C, const char *name)
|
||||
static int counter= 0;
|
||||
char filepath[FILE_MAXDIR+FILE_MAXFILE];
|
||||
char numstr[32];
|
||||
|
||||
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */
|
||||
|
||||
/* calculate current filepath */
|
||||
counter++;
|
||||
counter= counter % U.undosteps;
|
||||
@@ -531,7 +532,7 @@ void BKE_write_undo(bContext *C, const char *name)
|
||||
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
|
||||
BLI_make_file_string("/", filepath, btempdir, numstr);
|
||||
|
||||
success= BLO_write_file(CTX_data_main(C), filepath, G.fileflags, NULL, NULL);
|
||||
success= BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
|
||||
|
||||
BLI_strncpy(curundo->str, filepath, sizeof(curundo->str));
|
||||
}
|
||||
|
||||
@@ -2520,6 +2520,41 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
|
||||
return endwrite(wd);
|
||||
}
|
||||
|
||||
/* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */
|
||||
/* return: success(0), failure(1) */
|
||||
static int do_history(const char *name, ReportList *reports)
|
||||
{
|
||||
char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
|
||||
int hisnr= U.versions;
|
||||
|
||||
if(U.versions==0) return 0;
|
||||
if(strlen(name)<2) {
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while(hisnr > 1) {
|
||||
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1);
|
||||
BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr);
|
||||
|
||||
if(BLI_rename(tempname1, tempname2)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
|
||||
return 1;
|
||||
}
|
||||
hisnr--;
|
||||
}
|
||||
|
||||
/* is needed when hisnr==1 */
|
||||
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr);
|
||||
|
||||
if(BLI_rename(name, tempname1)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return: success (1) */
|
||||
int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb)
|
||||
{
|
||||
@@ -2571,48 +2606,55 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
|
||||
err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb);
|
||||
close(file);
|
||||
|
||||
/* rename/compress */
|
||||
if(!err) {
|
||||
if(write_flags & G_FILE_COMPRESS) {
|
||||
/* compressed files have the same ending as regular files... only from 2.4!!! */
|
||||
char gzname[FILE_MAXDIR+FILE_MAXFILE+4];
|
||||
int ret;
|
||||
|
||||
/* first write compressed to separate @.gz */
|
||||
BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
|
||||
ret = BLI_gzip(tempname, gzname);
|
||||
|
||||
if(0==ret) {
|
||||
/* now rename to real file name, and delete temp @ file too */
|
||||
if(BLI_rename(gzname, filepath) != 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLI_delete(tempname, 0, 0);
|
||||
}
|
||||
else if(-1==ret) {
|
||||
BKE_report(reports, RPT_ERROR, "Failed opening .gz file.");
|
||||
return 0;
|
||||
}
|
||||
else if(-2==ret) {
|
||||
BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(BLI_rename(tempname, filepath) != 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
if (err) {
|
||||
BKE_report(reports, RPT_ERROR, strerror(errno));
|
||||
remove(tempname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* file save to temporary file was successful */
|
||||
/* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */
|
||||
if (write_flags & G_FILE_HISTORY) {
|
||||
int err_hist = do_history(filepath, reports);
|
||||
if (err_hist) {
|
||||
BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(write_flags & G_FILE_COMPRESS) {
|
||||
/* compressed files have the same ending as regular files... only from 2.4!!! */
|
||||
char gzname[FILE_MAXDIR+FILE_MAXFILE+4];
|
||||
int ret;
|
||||
|
||||
/* first write compressed to separate @.gz */
|
||||
BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
|
||||
ret = BLI_gzip(tempname, gzname);
|
||||
|
||||
if(0==ret) {
|
||||
/* now rename to real file name, and delete temp @ file too */
|
||||
if(BLI_rename(gzname, filepath) != 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLI_delete(tempname, 0, 0);
|
||||
}
|
||||
else if(-1==ret) {
|
||||
BKE_report(reports, RPT_ERROR, "Failed opening .gz file.");
|
||||
return 0;
|
||||
}
|
||||
else if(-2==ret) {
|
||||
BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if(BLI_rename(tempname, filepath) != 0) {
|
||||
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -620,31 +620,6 @@ static void write_history(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_history(char *name, ReportList *reports)
|
||||
{
|
||||
char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
|
||||
int hisnr= U.versions;
|
||||
|
||||
if(U.versions==0) return;
|
||||
if(strlen(name)<2) return;
|
||||
|
||||
while(hisnr > 1) {
|
||||
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1);
|
||||
BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr);
|
||||
|
||||
if(BLI_rename(tempname1, tempname2))
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
|
||||
|
||||
hisnr--;
|
||||
}
|
||||
|
||||
/* is needed when hisnr==1 */
|
||||
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr);
|
||||
|
||||
if(BLI_rename(name, tempname1))
|
||||
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
|
||||
}
|
||||
|
||||
static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt)
|
||||
{
|
||||
/* will be scaled down, but gives some nice oversampling */
|
||||
@@ -693,9 +668,11 @@ static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt)
|
||||
int write_crash_blend(void)
|
||||
{
|
||||
char path[FILE_MAX];
|
||||
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */
|
||||
|
||||
BLI_strncpy(path, G.main->name, sizeof(path));
|
||||
BLI_replace_extension(path, sizeof(path), "_crash.blend");
|
||||
if(BLO_write_file(G.main, path, G.fileflags, NULL, NULL)) {
|
||||
if(BLO_write_file(G.main, path, fileflags, NULL, NULL)) {
|
||||
printf("written: %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
@@ -753,8 +730,7 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re
|
||||
/* blend file thumbnail */
|
||||
ibuf_thumb= blend_file_thumb(CTX_data_scene(C), &thumb);
|
||||
|
||||
/* rename to .blend1, do this as last before write */
|
||||
do_history(filepath, reports);
|
||||
fileflags |= G_FILE_HISTORY; /* write file history */
|
||||
|
||||
if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) {
|
||||
if(!copy) {
|
||||
@@ -809,7 +785,7 @@ int WM_write_homefile(bContext *C, wmOperator *op)
|
||||
printf("trying to save homefile at %s ", filepath);
|
||||
|
||||
/* force save as regular blend file */
|
||||
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN);
|
||||
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
|
||||
|
||||
if(BLO_write_file(CTX_data_main(C), filepath, fileflags, op->reports, NULL) == 0) {
|
||||
printf("fail\n");
|
||||
@@ -883,7 +859,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
|
||||
wm_autosave_location(filepath);
|
||||
|
||||
/* force save as regular blend file */
|
||||
fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN);
|
||||
fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN|G_FILE_HISTORY);
|
||||
|
||||
/* no error reporting to console */
|
||||
BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
|
||||
|
||||
Reference in New Issue
Block a user