Cleanup: split file read and setup into separate steps

Currently file loading performs almost all reloading logic
even in the case loading the file fails, causing the file to be in
a state that isn't well defined: undo is cleared, timers are canceled &
scripts are re-registered.
This commit is contained in:
Campbell Barton 2021-03-12 00:34:21 +11:00
parent f7616c6eaf
commit 5812bc7d89
4 changed files with 128 additions and 118 deletions

View File

@ -23,6 +23,7 @@
extern "C" {
#endif
struct BlendFileData;
struct BlendFileReadParams;
struct ID;
struct Main;
@ -31,36 +32,32 @@ struct ReportList;
struct UserDef;
struct bContext;
bool BKE_blendfile_read_ex(struct bContext *C,
const char *filepath,
const struct BlendFileReadParams *params,
struct ReportList *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template);
bool BKE_blendfile_read(struct bContext *C,
const char *filepath,
const struct BlendFileReadParams *params,
struct ReportList *reports);
void BKE_blendfile_read_setup_ex(struct bContext *C,
struct BlendFileData *bfd,
const struct BlendFileReadParams *params,
struct ReportList *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template);
bool BKE_blendfile_read_from_memory_ex(struct bContext *C,
const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
struct ReportList *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template);
bool BKE_blendfile_read_from_memory(struct bContext *C,
const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
struct ReportList *reports);
void BKE_blendfile_read_setup(struct bContext *C,
struct BlendFileData *bfd,
const struct BlendFileReadParams *params,
struct ReportList *reports);
bool BKE_blendfile_read_from_memfile(struct bContext *C,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
struct ReportList *reports);
struct BlendFileData *BKE_blendfile_read(const char *filepath,
const struct BlendFileReadParams *params,
struct ReportList *reports);
struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
struct ReportList *reports);
struct BlendFileData *BKE_blendfile_read_from_memfile(struct Main *bmain,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
struct ReportList *reports);
void BKE_blendfile_read_make_empty(struct bContext *C);
struct UserDef *BKE_blendfile_userdef_read(const char *filepath, struct ReportList *reports);

View File

@ -77,7 +77,12 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu,
G.fileflags |= G_FILE_NO_UI;
if (UNDO_DISK) {
success = BKE_blendfile_read(C, mfu->filename, &(const struct BlendFileReadParams){0}, NULL);
const struct BlendFileReadParams params = {0};
struct BlendFileData *bfd = BKE_blendfile_read(mfu->filename, &params, NULL);
if (bfd != NULL) {
BKE_blendfile_read_setup(C, bfd, &params, NULL);
success = true;
}
}
else {
struct BlendFileReadParams params = {0};
@ -85,7 +90,12 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu,
if (!use_old_bmain_data) {
params.skip_flags |= BLO_READ_SKIP_UNDO_OLD_MAIN;
}
success = BKE_blendfile_read_from_memfile(C, &mfu->memfile, &params, NULL);
struct BlendFileData *bfd = BKE_blendfile_read_from_memfile(
bmain, &mfu->memfile, &params, NULL);
if (bfd != NULL) {
BKE_blendfile_read_setup(C, bfd, &params, NULL);
success = true;
}
}
/* Restore, bmain has been re-allocated. */

View File

@ -429,15 +429,46 @@ static void handle_subversion_warning(Main *main, ReportList *reports)
}
}
bool BKE_blendfile_read_ex(bContext *C,
const char *filepath,
const struct BlendFileReadParams *params,
ReportList *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template)
/**
* Shared setup function that makes the data from `bfd` into the current blend file,
* replacing the contents of #G.main.
* This uses the bfd #BKE_blendfile_read and similarly named functions.
*
* This is done in a separate step so the caller may perform actions after it is known the file
* loaded correctly but before the file replaces the existing blend file contents.
*/
void BKE_blendfile_read_setup_ex(bContext *C,
BlendFileData *bfd,
const struct BlendFileReadParams *params,
ReportList *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template)
{
if (startup_update_defaults) {
if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
BLO_update_defaults_startup_blend(bfd->main, startup_app_template);
}
}
setup_app_blend_file_data(C, bfd, params, reports);
BLO_blendfiledata_free(bfd);
}
void BKE_blendfile_read_setup(bContext *C,
BlendFileData *bfd,
const struct BlendFileReadParams *params,
ReportList *reports)
{
BKE_blendfile_read_setup_ex(C, bfd, params, reports, false, NULL);
}
/**
* \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
*/
struct BlendFileData *BKE_blendfile_read(const char *filepath,
const struct BlendFileReadParams *params,
ReportList *reports)
{
/* Don't print startup file loading. */
if (params->is_startup == false) {
printf("Read blend: %s\n", filepath);
@ -446,69 +477,40 @@ bool BKE_blendfile_read_ex(bContext *C,
BlendFileData *bfd = BLO_read_from_file(filepath, params->skip_flags, reports);
if (bfd) {
handle_subversion_warning(bfd->main, reports);
if (startup_update_defaults) {
if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
BLO_update_defaults_startup_blend(bfd->main, startup_app_template);
}
}
setup_app_blend_file_data(C, bfd, params, reports);
BLO_blendfiledata_free(bfd);
}
else {
BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath);
}
return (bfd != NULL);
return bfd;
}
bool BKE_blendfile_read(bContext *C,
const char *filepath,
const struct BlendFileReadParams *params,
ReportList *reports)
{
return BKE_blendfile_read_ex(C, filepath, params, reports, false, NULL);
}
bool BKE_blendfile_read_from_memory_ex(bContext *C,
const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
ReportList *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template)
/**
* \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
*/
struct BlendFileData *BKE_blendfile_read_from_memory(const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
ReportList *reports)
{
BlendFileData *bfd = BLO_read_from_memory(filebuf, filelength, params->skip_flags, reports);
if (bfd) {
if (startup_update_defaults) {
if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
BLO_update_defaults_startup_blend(bfd->main, startup_app_template);
}
}
setup_app_blend_file_data(C, bfd, params, reports);
BLO_blendfiledata_free(bfd);
/* Pass. */
}
else {
BKE_reports_prepend(reports, "Loading failed: ");
}
return (bfd != NULL);
return bfd;
}
bool BKE_blendfile_read_from_memory(bContext *C,
const void *filebuf,
int filelength,
const struct BlendFileReadParams *params,
ReportList *reports)
/**
* \return Blend file data, this must be passed to #BKE_blendfile_read_setup when non-NULL.
* \note `memfile` is the undo buffer.
*/
struct BlendFileData *BKE_blendfile_read_from_memfile(Main *bmain,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
ReportList *reports)
{
return BKE_blendfile_read_from_memory_ex(C, filebuf, filelength, params, reports, false, NULL);
}
/* memfile is the undo buffer */
bool BKE_blendfile_read_from_memfile(bContext *C,
struct MemFile *memfile,
const struct BlendFileReadParams *params,
ReportList *reports)
{
Main *bmain = CTX_data_main(C);
BlendFileData *bfd = BLO_read_from_memfile(
bmain, BKE_main_blendfile_path(bmain), memfile, params, reports);
if (bfd) {
@ -519,14 +521,11 @@ bool BKE_blendfile_read_from_memfile(bContext *C,
BLI_assert(BLI_listbase_is_empty(&bfd->main->wm));
BLI_assert(BLI_listbase_is_empty(&bfd->main->workspaces));
BLI_assert(BLI_listbase_is_empty(&bfd->main->screens));
setup_app_blend_file_data(C, bfd, params, reports);
BLO_blendfiledata_free(bfd);
}
else {
BKE_reports_prepend(reports, "Loading failed: ");
}
return (bfd != NULL);
return bfd;
}
/**

View File

@ -729,17 +729,19 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* also exit screens and editors */
wm_window_match_init(C, &wmbase);
success = BKE_blendfile_read(
C,
filepath,
/* Loading preferences when the user intended to load a regular file is a security risk,
* because the excluded path list is also loaded.
* Further it's just confusing if a user loads a file and various preferences change. */
&(const struct BlendFileReadParams){
.is_startup = false,
.skip_flags = BLO_READ_SKIP_USERDEF,
},
reports);
const struct BlendFileReadParams params = {
.is_startup = false,
/* Loading preferences when the user intended to load a regular file is a security
* risk, because the excluded path list is also loaded. Further it's just confusing
* if a user loads a file and various preferences change. */
.skip_flags = BLO_READ_SKIP_USERDEF,
};
struct BlendFileData *bfd = BKE_blendfile_read(filepath, &params, reports);
if (bfd != NULL) {
BKE_blendfile_read_setup(C, bfd, &params, reports);
success = true;
}
/* BKE_file_read sets new Main into context. */
Main *bmain = CTX_data_main(C);
@ -1040,15 +1042,17 @@ void wm_homefile_read(bContext *C,
if (!use_factory_settings || (filepath_startup[0] != '\0')) {
if (BLI_access(filepath_startup, R_OK) == 0) {
success = BKE_blendfile_read_ex(C,
filepath_startup,
&(const struct BlendFileReadParams){
.is_startup = true,
.skip_flags = skip_flags | BLO_READ_SKIP_USERDEF,
},
NULL,
update_defaults && use_data,
app_template);
const struct BlendFileReadParams params = {
.is_startup = true,
.skip_flags = skip_flags | BLO_READ_SKIP_USERDEF,
};
struct BlendFileData *bfd = BKE_blendfile_read(filepath_startup, &params, NULL);
if (bfd != NULL) {
BKE_blendfile_read_setup_ex(
C, bfd, &params, NULL, update_defaults && use_data, app_template);
success = true;
}
}
if (success) {
is_factory_startup = filepath_startup_is_factory;
@ -1069,16 +1073,16 @@ void wm_homefile_read(bContext *C,
}
if (success == false) {
success = BKE_blendfile_read_from_memory_ex(C,
datatoc_startup_blend,
datatoc_startup_blend_size,
&(const struct BlendFileReadParams){
.is_startup = true,
.skip_flags = skip_flags,
},
NULL,
true,
NULL);
const struct BlendFileReadParams params = {
.is_startup = true,
.skip_flags = skip_flags,
};
struct BlendFileData *bfd = BKE_blendfile_read_from_memory(
datatoc_startup_blend, datatoc_startup_blend_size, &params, NULL);
if (bfd != NULL) {
BKE_blendfile_read_setup_ex(C, bfd, &params, NULL, true, NULL);
success = true;
}
if (use_data && BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);