NEW! Subversion control and test for future Blender binaries.

Next to the release code, a subversion number is written in the file
now. This is in the chunk GLOB, which is now in beginning of file.

Subversions can be used to have finer control over do_versions(), so you
don't have to wait for a release to patch stuff nicely. We can also
increase these subversions regularly to denote important changes.
If a subversion is not 0, it's being printed in the header, so a user can
also verify the state. (We might even tag cvs for it?).

Next to this, a minimum version and subversion number are written too.
From now on, if you change files in a way a past binary cannot read this
nicely anymore, you should set these minima to the current version.
This was especially added for the new mesh layers, which will not work
for older binaries once we make 2.43.
This commit is contained in:
Ton Roosendaal 2006-11-26 21:17:15 +00:00
parent b36bafe524
commit 0cd62a9298
7 changed files with 94 additions and 11 deletions

@ -43,7 +43,11 @@ extern "C" {
struct ListBase;
struct MemFile;
#define BLENDER_VERSION 242
#define BLENDER_VERSION 242
#define BLENDER_SUBVERSION 1
#define BLENDER_MINVERSION 240
#define BLENDER_MINSUBVERSION 0
int BKE_read_file(char *dir, void *type_r);
int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r);

@ -48,7 +48,9 @@ struct Library;
typedef struct Main {
struct Main *next, *prev;
char name[160];
short versionfile, rt;
short versionfile, subversionfile;
short minversionfile, minsubversionfile;
struct Library *curlib;
ListBase scene;
ListBase library;

@ -213,7 +213,10 @@ void initglobals(void)
G.order= 1;
G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN;
sprintf(versionstr, "www.blender.org %d", G.version);
if(BLENDER_SUBVERSION)
sprintf(versionstr, "www.blender.org %d.%d", G.version, BLENDER_SUBVERSION);
else
sprintf(versionstr, "www.blender.org %d", G.version);
#ifdef _WIN32 // FULLSCREEN
G.windowstate = G_WINDOWSTATE_USERDEF;
@ -411,6 +414,20 @@ static void setup_app_data(BlendFileData *bfd, char *filename)
MEM_freeN(bfd);
}
static void handle_subversion_warning(Main *main)
{
if(main->minversionfile > BLENDER_VERSION ||
(main->minversionfile == BLENDER_VERSION &&
main->minsubversionfile > BLENDER_SUBVERSION)) {
char str[128];
sprintf(str, "File written by newer Blender binary: %d.%d , expect loss of data!", main->minversionfile, main->minsubversionfile);
error(str);
}
}
/* returns:
0: no load file
1: OK
@ -433,7 +450,10 @@ int BKE_read_file(char *dir, void *type_r)
*((BlenFileType*)type_r)= bfd->type;
setup_app_data(bfd, dir);
} else {
handle_subversion_warning(bfd->main);
}
else {
error("Loading %s failed: %s", dir, BLO_bre_as_string(bre));
}

@ -240,7 +240,7 @@ typedef struct OldNewMap {
/* local prototypes */
extern short freeN(void *vmemh); /* defined in util.h */
static void *read_struct(FileData *fd, BHead *bh, char *blockname);
static OldNewMap *oldnewmap_new(void)
@ -719,6 +719,25 @@ BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
return(bhead);
}
static void get_blender_subversion(FileData *fd)
{
BHead *bhead;
for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
if (bhead->code==GLOB) {
FileGlobal *fg= read_struct(fd, bhead, "Global");
fd->filesubversion= fg->subversion;
fd->fileminversion= fg->minversion;
fd->fileminsubversion= fg->minsubversion;
MEM_freeN(fg);
return;
}
else if (bhead->code==ENDB)
break;
}
}
static void decode_blender_header(FileData *fd)
{
char header[SIZEOFBLENDERHEADER], num[4];
@ -779,6 +798,7 @@ static int read_file_dna(FileData *fd)
return 0;
}
static int fd_read_from_file(FileData *filedata, void *buffer, int size)
{
int readsize = read(filedata->filedes, buffer, size);
@ -896,7 +916,12 @@ static FileData *blo_decode_and_check(FileData *fd, BlendReadError *error_r)
blo_freefiledata(fd);
fd= NULL;
}
} else {
// subversion, stored in GLOB since 2.42
if(fd->fileversion>=242)
get_blender_subversion(fd);
}
else {
*error_r = BRE_NOT_A_BLEND;
blo_freefiledata(fd);
fd= NULL;
@ -3984,6 +4009,7 @@ static void link_global(FileData *fd, BlendFileData *bfd, FileGlobal *fg)
bfd->fileflags= fg->fileflags;
bfd->displaymode= fg->displaymode;
bfd->globalf= fg->globalf;
bfd->curscreen= newlibadr(fd, 0, fg->curscreen);
bfd->curscene= newlibadr(fd, 0, fg->curscene);
// this happens in files older than 2.35
@ -6097,6 +6123,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
/* History fix (python?), shape key adrcode numbers have to be sorted */
sort_shape_fix(main);
/* now, subversion control! */
if(main->subversionfile < 1) {
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
@ -6168,6 +6199,9 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
BLI_addtail(&fd->mainlist, bfd->main);
bfd->main->versionfile= fd->fileversion;
bfd->main->subversionfile= fd->filesubversion;
bfd->main->minversionfile= fd->fileminversion;
bfd->main->minsubversionfile= fd->fileminsubversion;
while(bhead) {
switch(bhead->code) {
@ -6177,7 +6211,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
case TEST:
case REND:
if (bhead->code==GLOB) {
fg= read_struct(fd, bhead, "REND");
fg= read_struct(fd, bhead, "Global");
}
bhead = blo_nextbhead(fd, bhead);
break;
@ -7060,7 +7094,12 @@ void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
/* which one do we need? */
mainl = blo_find_main(&fd->mainlist, dir, G.sce);
mainl->versionfile= fd->fileversion; // needed for do_version
mainl->subversionfile= fd->filesubversion;
mainl->minversionfile= fd->fileminversion;
mainl->minsubversionfile= fd->fileminsubversion;
curlib= mainl->curlib;
if(totsel==0) {
@ -7200,6 +7239,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
mainptr->curlib->filedata= fd;
mainptr->versionfile= fd->fileversion;
mainptr->subversionfile= fd->filesubversion;
mainptr->minversionfile= fd->fileminversion;
mainptr->minsubversionfile= fd->fileminsubversion;
}
else mainptr->curlib->filedata= NULL;

@ -68,7 +68,8 @@ typedef struct FileData {
struct SDNA *memsdna;
char *compflags;
int fileversion;
int fileversion, filesubversion;
int fileminversion, fileminsubversion;
struct OldNewMap *datamap;
struct OldNewMap *globmap;
@ -89,6 +90,7 @@ typedef struct BHeadN {
struct BHead bhead;
} BHeadN;
#define FD_FLAGS_SWITCH_ENDIAN (1<<0)
#define FD_FLAGS_FILE_POINTSIZE_IS_4 (1<<1)
#define FD_FLAGS_POINTSIZE_DIFFERS (1<<2)

@ -153,6 +153,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
#include "BKE_action.h"
#include "BKE_bad_level_calls.h" // build_seqar (from WHILE_SEQ) free_oops error
#include "BKE_blender.h"
#include "BKE_curve.h"
#include "BKE_constraint.h"
#include "BKE_global.h" // for G
@ -474,7 +475,7 @@ static void write_scriptlink(WriteData *wd, ScriptLink *slink)
writedata(wd, DATA, sizeof(short)*slink->totscript, slink->flag);
}
static void write_renderinfo(WriteData *wd) /* for renderdaemon */
static void write_renderinfo(WriteData *wd) /* for renderdeamon */
{
Scene *sce;
int data[8];
@ -1843,6 +1844,9 @@ static void write_global(WriteData *wd)
fg.winpos= G.winpos;
fg.fileflags= (G.fileflags & ~G_FILE_NO_UI); // prevent to save this, is not good convention, and feature with concerns...
fg.globalf= G.f;
fg.subversion= BLENDER_SUBVERSION;
fg.minversion= BLENDER_MINVERSION;
fg.minsubversion= BLENDER_MINSUBVERSION;
writestruct(wd, GLOB, "FileGlobal", 1, &fg);
}
@ -1863,7 +1867,8 @@ static int write_file_handle(int handle, MemFile *compare, MemFile *current, int
mywrite(wd, buf, 12);
write_renderinfo(wd);
write_global(wd);
if(current==NULL)
write_screens (wd, &G.main->screen); /* no UI save in undo */
write_scenes (wd, &G.main->scene);
@ -1891,7 +1896,6 @@ static int write_file_handle(int handle, MemFile *compare, MemFile *current, int
if(current==NULL)
write_libraries(wd, G.main->next); /* no library save in undo */
write_global(wd);
if (write_user_block) {
write_userdef(wd);
}

@ -45,7 +45,16 @@ typedef struct FileGlobal {
int fileflags;
int globalf;
int pad;
short subversion, pads;
short minversion, minsubversion;
} FileGlobal;
/* minversion: in file, the oldest past blender version you can use compliant */
/* example: if in 2.43 the meshes lose mesh data, minversion is 2.43 then too */
/* or: in 2.42, subversion 1, same as above, minversion then is 2.42, min subversion 1 */
/* (defines for version are in the BKE_blender.h file, for historic reasons) */
#endif