Implemented experimental library resource bundle versioning

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@24841 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Nicola Pero 2007-03-09 19:09:08 +00:00
parent c2d8270d8c
commit c641207ab8
8 changed files with 177 additions and 41 deletions

View file

@ -1,3 +1,42 @@
2007-03-09 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented library resource bundle versioning. Updated
gnustep-base to use versioned resources.
* Source/NSBundle ([+bundleForLibrary:version]): New method.
Allow to request the resource bundle for a specific version.
Changed bundle resource location to be
GNUSTEP_LIBRARY/Libraries/<libraryName>/Versions/<interfaceVersion>/Resources
to allow versioned resources and be similar to framework resources
- will be handy in the future. Fall back to the old unversioned
bundle at GNUSTEP_LIBRARY/Libraries/Resources/<libraryName> if no
specific version is required and no versioned bundle can be found.
([+bundleForLibrary:]): Implemented in terms of
+bundleForLibrary:version:. Should be backwards compatible if
you're not using resource versioning yet.
([+initialize]): When creating _gnustep_bundle, use
[+bundleForLibrary:version:] to get the appropriate version of the
bundle.
* Headers/Foundation/NSBundle.h ([+bundleForLibrary:version:]):
New method; updated documentation for this method and for
[+bundleForLibrary:].
* Resources/GNUmakefile: Include ../Version and install into the
new versioned directory.
* NSTimeZones/GNUmakefile: Same changes.
* Source/GNUmakefile: Same changes.
* Source/NSBundle.m ([+bundleForClass:]): If we are asked for the
bundle for NSObject, return _gnustep_bundle (prepared during
+initialize) immediately.
* Source/NSTimeZone.m (_time_zone_path): Use bundleForClass:
NSObject to get the gnustep-base bundle immediately and safely.
* Source/NSUserDefaults.m ([+standardUserDefaults]): Same change.
* Source/GNUmakefile (libgnustep-base_INTERFACE_VERSION,
libgnustep-baseadd_INTERFACE_VERSION): Use more standard makefile
syntax.
2007-03-09 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSProcessInfo.m: On mswindows, don't count a '.exe'

View file

@ -387,11 +387,17 @@ GS_EXPORT NSString* const NSLoadedClasses;
@interface NSBundle (GNUstep)
/** This method is an experimental GNUstep extension, and might change.
* <p>Return a bundle which accesses the first existing directory from
* the standard libraries directories whose Resources subdirectory
* contains libraryName.
* Where libraryName is the name of a library without the <em>lib</em>
* prefix or any extensions.
* <p>Return a bundle to access the resources for the (static or shared) library
* libraryName, with interface version interfaceVersion.
* </p>
* <p>Resources for shared libraries are stored into
* GNUSTEP_LIBRARY/Libraries/libraryName/Versions/interfaceVersion/Resources/;
* this method will search for the first such existing directory and return it.
*</p>
* <p>libraryName should be the name of a library without the
* <em>lib</em> prefix or any extensions; interfaceVersion is the
* interface version of the library (eg, it's 1.13 in libgnustep-base.so.1.13;
* see library.make on how to control it).
* </p>
* <p>This method exists to provide resource bundles for libraries and has no
* particular relationship to the library code itsself. The named library
@ -409,8 +415,16 @@ GS_EXPORT NSString* const NSLoadedClasses;
* not exist on disk.
* </p>
*/
+ (NSBundle *) bundleForLibrary: (NSString *)libraryName
version: (NSString *)interfaceVersion;
/** This method is a equivalent to bundleForLibrary:version: with a nil
* version.
*/
+ (NSBundle *) bundleForLibrary: (NSString *)libraryName;
/** Find a resource in the "Library" directory. */
+ (NSString*) pathForLibraryResource: (NSString*)name
ofType: (NSString*)ext

View file

@ -39,7 +39,9 @@ include $(GNUSTEP_MAKEFILES)/common.make
include ../Version
include ../config.mak
resourcedir = $(GNUSTEP_RESOURCES)/gnustep-base
libgnustep-base_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
resourcedir = $(GNUSTEP_LIBRARY)/Libraries/gnustep-base/Versions/$(libgnustep-base_INTERFACE_VERSION)/Resources
TIMEZONE_ARCHIVE = \
NSTimeZones.tar

View file

@ -36,9 +36,12 @@ GNUSTEP_LOCAL_ADDITIONAL_MAKEFILES=../base.make
include $(GNUSTEP_MAKEFILES)/common.make
include ../Version
libgnustep-base_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
RESOURCE_SET_NAME = base-resources
# This is for gnustep-make >= 14-02-2007
base-resources_INSTALL_DIR = $(GNUSTEP_RESOURCES)/gnustep-base
base-resources_INSTALL_DIR = $(GNUSTEP_LIBRARY)/Libraries/gnustep-base/Versions/$(libgnustep-base_INTERFACE_VERSION)/Resources
# This is kept temporarily for gnustep-make < 14-02-2007
base-resources_RESOURCE_FILES_INSTALL_DIR = /Library/Libraries/Resources/gnustep-base
base-resources_LANGUAGES = English German French Italian TraditionalChinese \

View file

@ -42,8 +42,8 @@ include ../Version
include ../config.mak
# Interface version changes with each minor release
libgnustep-base_INTERFACE_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}
libgnustep-baseadd_INTERFACE_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}
libgnustep-base_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
libgnustep-baseadd_INTERFACE_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
PACKAGE_NAME = gnustep-base
@ -421,7 +421,7 @@ libgnustep-base_HEADER_FILES = $(FOUNDATION_HEADERS)
RESOURCE_SET_NAME = libbase-resources
# This is for gnustep-make >= 14-02-2007
libbase-resources_INSTALL_DIR = $(GNUSTEP_LIBRARY)/Libraries/Resources/gnustep-base
libbase-resources_INSTALL_DIR = $(GNUSTEP_LIBRARY)/Libraries/gnustep-base/Versions/$(libgnustep-base_INTERFACE_VERSION)/Resources
# This is kept temporarily for gnustep-make < 14-02-2007
libbase-resources_RESOURCE_FILES_INSTALL_DIR = /Library/Libraries/Resources/gnustep-base

View file

@ -806,7 +806,8 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
_launchDirectory = RETAIN([[NSFileManager defaultManager]
currentDirectoryPath]);
_gnustep_bundle = RETAIN([self bundleForLibrary: @"gnustep-base"]);
_gnustep_bundle = RETAIN([self bundleForLibrary: @"gnustep-base"
version: OBJC_STRINGIFY(GNUSTEP_BASE_MAJOR_VERSION.GNUSTEP_BASE_MINOR_VERSION)]);
#if 0
_loadingBundle = [self mainBundle];
@ -1095,6 +1096,14 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
if (!aClass)
return nil;
/* This is asked relatively frequently inside gnustep-base itself;
* shortcut it.
*/
if (aClass == [NSObject class])
{
return _gnustep_bundle;
}
[load_lock lock];
bundle = nil;
enumerate = NSEnumerateMapTable(_bundles);
@ -1127,8 +1136,8 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
/*
* Take the path to the binary containing the class and
* convert it to the format for a library name as used
* for obtaining a library resource bundle.
* convert it to the format for a library name as used for
* obtaining a library resource bundle.
*/
lib = GSPrivateSymbolPath (aClass, NULL);
if ([lib isEqual: GSPrivateExecutablePath()] == YES)
@ -1137,9 +1146,13 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
}
/*
* Get the library bundle ... if there wasn't one
* then we will assume the class was in the program
* executable and return the mainBundle instead.
* Get the library bundle ... if there wasn't one then we
* will assume the class was in the program executable and
* return the mainBundle instead.
*
* FIXME: This will not work well with versioned library
* resources. It used to work fine (maybe) with unversioned
* library resources.
*/
bundle = [NSBundle bundleForLibrary: lib];
if (bundle == nil)
@ -1148,9 +1161,9 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
}
/*
* Add the class to the list of classes known to be in
* the library or executable. We didn't find it there
* to start with, so we know it's safe to add now.
* Add the class to the list of classes known to be in the
* library or executable. We didn't find it there to start
* with, so we know it's safe to add now.
*/
if (bundle->_bundleClasses == nil)
{
@ -2176,11 +2189,16 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
@implementation NSBundle (GNUstep)
+ (NSBundle *) bundleForLibrary: (NSString *)libraryName
{
return [self bundleForLibrary: libraryName version: nil];
}
+ (NSBundle *) bundleForLibrary: (NSString *)libraryName
version: (NSString *)interfaceVersion
{
NSArray *paths;
NSEnumerator *enumerator;
NSString *path;
NSString *tail;
NSFileManager *fm = [NSFileManager defaultManager];
/*
@ -2199,41 +2217,101 @@ _bundle_load_callback(Class theClass, struct objc_category *theCategory)
{
libraryName = [libraryName substringFromIndex: 3];
}
/*
* Discard debug/profile library suffix
*/
if ([libraryName hasSuffix: @"_d"] == YES
|| [libraryName hasSuffix: @"_p"] == YES)
{
libraryName = [libraryName substringToIndex: [libraryName length] - 3];
}
if ([libraryName length] == 0)
{
return nil;
}
tail = [@"Libraries" stringByAppendingPathComponent:
[@"Resources" stringByAppendingPathComponent: libraryName]];
/*
* We expect to find the library resources into:
*
* GNUSTEP_LIBRARY/Libraries/<libraryName>/Versions/<interfaceVersion>/Resources/
*
* if no <interfaceVersion> is specified, and if can't find any versioned
* resources in those directories, we'll also accept the old unversioned format
*
* GNUSTEP_LIBRARY/Libraries/Resources/<libraryName>/
*
*/
paths = NSSearchPathForDirectoriesInDomains (NSLibraryDirectory,
NSAllDomainsMask, YES);
enumerator = [paths objectEnumerator];
while ((path = [enumerator nextObject]))
while ((path = [enumerator nextObject]) != nil)
{
NSBundle *b;
BOOL isDir;
path = [path stringByAppendingPathComponent: tail];
path = [path stringByAppendingPathComponent: @"Libraries"];
if ([fm fileExistsAtPath: path isDirectory: &isDir] && isDir)
{
NSBundle *b = [self bundleWithPath: path];
if (b != nil && b->_bundleType == NSBUNDLE_BUNDLE)
if (interfaceVersion != nil)
{
b->_bundleType = NSBUNDLE_LIBRARY;
/* We're looking for a specific version. */
path = [[[[path stringByAppendingPathComponent: libraryName]
stringByAppendingPathComponent: @"Versions"]
stringByAppendingPathComponent: interfaceVersion]
stringByAppendingPathComponent: @"Resources"];
if ([fm fileExistsAtPath: path isDirectory: &isDir] && isDir)
{
b = [self bundleWithPath: path];
if (b != nil && b->_bundleType == NSBUNDLE_BUNDLE)
{
b->_bundleType = NSBUNDLE_LIBRARY;
}
return b;
}
}
else
{
/* Any version will do. */
NSString *versionsPath = [[path stringByAppendingPathComponent: libraryName]
stringByAppendingPathComponent: @"Versions"];
if ([fm fileExistsAtPath: versionsPath isDirectory: &isDir] && isDir)
{
NSEnumerator *fileEnumerator = [fm enumeratorAtPath: versionsPath];
NSString *potentialPath;
while ((potentialPath = [fileEnumerator nextObject]) != nil)
{
potentialPath = [potentialPath stringByAppendingPathComponent: @"Resources"];
if ([fm fileExistsAtPath: potentialPath isDirectory: &isDir] && isDir)
{
b = [self bundleWithPath: potentialPath];
if (b != nil && b->_bundleType == NSBUNDLE_BUNDLE)
{
b->_bundleType = NSBUNDLE_LIBRARY;
}
return b;
}
}
}
/* We didn't find anything! For backwards
* compatibility, try the unversioned directory itself:
* we used to put library resources directly in
* unversioned directories such as
* GNUSTEP_LIBRARY/Libraries/Resources/gnustep-base/{resources
* here}. This was deprecated/obsoleted on 9 March 2007
* when we added library resource versioning.
*/
{
NSString *oldResourcesPath = [[path stringByAppendingPathComponent: @"Resources"]
stringByAppendingPathComponent: libraryName];
if ([fm fileExistsAtPath: oldResourcesPath isDirectory: &isDir] && isDir)
{
b = [self bundleWithPath: oldResourcesPath];
if (b != nil && b->_bundleType == NSBUNDLE_BUNDLE)
{
b->_bundleType = NSBUNDLE_LIBRARY;
}
return b;
}
}
}
return b;
}
}

View file

@ -273,7 +273,7 @@ static NSString *_time_zone_path(NSString *subpath, NSString *type)
NSBundle *gbundle;
if (type == nil)
type = @"";
gbundle = [NSBundle bundleForLibrary: @"gnustep-base"];
gbundle = [NSBundle bundleForClass: [NSObject class]];
return [gbundle pathForResource: subpath
ofType: type
inDirectory: TIME_ZONE_DIR];

View file

@ -502,7 +502,7 @@ static BOOL setSharedDefaults = NO; /* Flag to prevent infinite recursion */
NSDictionary *dict;
NSBundle *gbundle;
gbundle = [NSBundle bundleForLibrary: @"gnustep-base"];
gbundle = [NSBundle bundleForClass: [NSObject class]];
path = [gbundle pathForResource: lang
ofType: nil
inDirectory: @"Languages"];