Merged in lindenlab/viewer-lynx
commit
37809faefa
|
|
@ -70,15 +70,12 @@ additional_packages = ""
|
|||
# the viewer_channel_suffix is prefixed by a blank and then appended to the viewer_channel
|
||||
# for the package in a setting that overrides the compiled-in value
|
||||
################################################################
|
||||
## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
|
||||
## additional_packages = "EDU"
|
||||
additional_packages = "EDU"
|
||||
|
||||
# The EDU package allows us to create a separate release channel whose expirations
|
||||
# are synchronized as much as possible with the academic year
|
||||
## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
|
||||
## EDU_sourceid = ""
|
||||
## Removed 2015-07-02 (MAINT-5360) until we fix packaging step in Team City
|
||||
## EDU_viewer_channel_suffix = "edu"
|
||||
EDU_sourceid = ""
|
||||
EDU_viewer_channel_suffix = "edu"
|
||||
|
||||
# Notifications - to configure email notices, add a setting like this:
|
||||
# <username>_<reponame>.email = <email-address>
|
||||
|
|
|
|||
|
|
@ -141,6 +141,43 @@ if (LL_TESTS)
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llcorehttp_peer.py"
|
||||
)
|
||||
|
||||
if (DARWIN)
|
||||
# Path inside the app bundle where we'll need to copy libraries
|
||||
set(LL_TEST_DESTINATION_DIR
|
||||
${CMAKE_SOURCE_DIR}/../build-darwin-i386/sharedlibs/Resources
|
||||
)
|
||||
|
||||
# Create the Contents/Resources directory
|
||||
add_custom_command(
|
||||
TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
-E
|
||||
make_directory
|
||||
${LL_TEST_DESTINATION_DIR}
|
||||
COMMENT "Creating Resources directory in app bundle."
|
||||
)
|
||||
|
||||
# Copy the required libraries to the package app
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib
|
||||
)
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib
|
||||
)
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib
|
||||
)
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib
|
||||
)
|
||||
|
||||
endif (DARWIN)
|
||||
|
||||
#
|
||||
# Example Programs
|
||||
#
|
||||
|
|
|
|||
|
|
@ -114,4 +114,12 @@ if (DARWIN)
|
|||
LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
|
||||
)
|
||||
|
||||
add_custom_command(TARGET media_plugin_cef
|
||||
POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "@executable_path/Chromium Embedded Framework"
|
||||
"@executable_path/../../../../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework"
|
||||
"$<TARGET_FILE:media_plugin_cef>"
|
||||
VERBATIM
|
||||
COMMENT "Fixing path to CEF Framework"
|
||||
)
|
||||
|
||||
endif (DARWIN)
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ LLLocalBitmap::~LLLocalBitmap()
|
|||
}
|
||||
|
||||
// delete self from gimagelist
|
||||
LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture* image = gTextureList.findImage(mWorldID, TEX_LIST_DISCARD);
|
||||
gTextureList.deleteImage(image);
|
||||
|
||||
if (image)
|
||||
|
|
@ -207,7 +207,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
|
|||
texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image);
|
||||
texture->ref();
|
||||
|
||||
gTextureList.addImage(texture, TEX_LIST_STANDARD);
|
||||
gTextureList.addImage(texture, TEX_LIST_DISCARD);
|
||||
|
||||
if (optional_firstupdate != UT_FIRSTUSE)
|
||||
{
|
||||
|
|
@ -215,7 +215,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
|
|||
replaceIDs(old_id, mWorldID);
|
||||
|
||||
// remove old_id from gimagelist
|
||||
LLViewerFetchedTexture* image = gTextureList.findImage(old_id, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture* image = gTextureList.findImage(old_id, TEX_LIST_DISCARD);
|
||||
if (image != NULL)
|
||||
{
|
||||
gTextureList.deleteImage(image);
|
||||
|
|
@ -384,7 +384,7 @@ void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id)
|
|||
std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id, U32 channel)
|
||||
{
|
||||
std::vector<LLViewerObject*> obj_list;
|
||||
LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id, TEX_LIST_DISCARD);
|
||||
|
||||
for(U32 face_iterator = 0; face_iterator < old_texture->getNumFaces(channel); face_iterator++)
|
||||
{
|
||||
|
|
@ -502,7 +502,7 @@ void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id, U32 channel)
|
|||
|
||||
void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id)
|
||||
{
|
||||
LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id, TEX_LIST_DISCARD);
|
||||
for(U32 volume_iter = 0; volume_iter < old_texture->getNumVolumes(); volume_iter++)
|
||||
{
|
||||
LLVOVolume* volume_to_object = (*old_texture->getVolumeList())[volume_iter];
|
||||
|
|
|
|||
|
|
@ -2214,7 +2214,7 @@ void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical)
|
|||
LLTextureEntry *te = object->getTE(te_index);
|
||||
if (te)
|
||||
{
|
||||
LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL;
|
||||
LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_DISCARD) : NULL;
|
||||
if(!tex)
|
||||
{
|
||||
tex = LLViewerFetchedTexture::sDefaultImagep;
|
||||
|
|
|
|||
|
|
@ -1393,7 +1393,7 @@ void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb)
|
|||
|
||||
void LLTextureCtrl::setImageAssetName(const std::string& name)
|
||||
{
|
||||
LLPointer<LLUIImage> imagep = LLUI::getUIImage(name, LLGLTexture::BOOST_PREVIEW);
|
||||
LLPointer<LLUIImage> imagep = LLUI::getUIImage(name);
|
||||
if(imagep)
|
||||
{
|
||||
LLViewerFetchedTexture* pTexture = dynamic_cast<LLViewerFetchedTexture*>(imagep->getImage().get());
|
||||
|
|
|
|||
|
|
@ -4460,7 +4460,7 @@ void LLTextureFetchDebugger::addHistoryEntry(LLTextureFetchWorker* worker)
|
|||
mRefetchedAllData += worker->mFormattedImage->getDataSize();
|
||||
|
||||
// refetch list only requests/creates normal images, so requesting ui='false'
|
||||
LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture* tex = LLViewerTextureManager::findFetchedTexture(worker->mID, TEX_LIST_DISCARD);
|
||||
if(tex && mRefetchList[tex].begin() != mRefetchList[tex].end())
|
||||
{
|
||||
if(worker->mDecodedDiscard == mFetchingHistory[mRefetchList[tex][0]].mDecodedLevel)
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ LLViewerParcelMgr::LLViewerParcelMgr()
|
|||
// JC: Resolved a merge conflict here, eliminated
|
||||
// mBlockedImage->setAddressMode(LLTexUnit::TAM_WRAP);
|
||||
// because it is done in llviewertexturelist.cpp
|
||||
mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png");
|
||||
mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png");
|
||||
mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI);
|
||||
mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI);
|
||||
|
||||
S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS;
|
||||
sPackedOverlay = new U8[overlay_size];
|
||||
|
|
|
|||
|
|
@ -3323,7 +3323,7 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
|
|||
|
||||
setCategory(LLGLTexture::MEDIA);
|
||||
|
||||
LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD);
|
||||
LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_DISCARD);
|
||||
if(tex) //this media is a parcel media for tex.
|
||||
{
|
||||
tex->setParcelMedia(this);
|
||||
|
|
@ -3333,7 +3333,7 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
|
|||
//virtual
|
||||
LLViewerMediaTexture::~LLViewerMediaTexture()
|
||||
{
|
||||
LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD);
|
||||
LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_DISCARD);
|
||||
if(tex) //this media is a parcel media for tex.
|
||||
{
|
||||
tex->setParcelMedia(NULL);
|
||||
|
|
@ -3388,7 +3388,7 @@ BOOL LLViewerMediaTexture::findFaces()
|
|||
|
||||
BOOL ret = TRUE;
|
||||
|
||||
LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD);
|
||||
LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_DISCARD);
|
||||
if(tex) //this media is a parcel media for tex.
|
||||
{
|
||||
for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
|
||||
|
|
@ -3497,7 +3497,7 @@ void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep)
|
|||
const LLTextureEntry* te = facep->getTextureEntry();
|
||||
if(te && te->getID().notNull())
|
||||
{
|
||||
LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD);
|
||||
LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_DISCARD);
|
||||
if(tex)
|
||||
{
|
||||
mTextureList.push_back(tex);//increase the reference number by one for tex to avoid deleting it.
|
||||
|
|
@ -3526,7 +3526,7 @@ void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep)
|
|||
const LLTextureEntry* te = facep->getTextureEntry();
|
||||
if(te && te->getID().notNull())
|
||||
{
|
||||
LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD);
|
||||
LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_DISCARD);
|
||||
if(tex)
|
||||
{
|
||||
for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin();
|
||||
|
|
@ -3635,10 +3635,10 @@ void LLViewerMediaTexture::switchTexture(U32 ch, LLFace* facep)
|
|||
const LLTextureEntry* te = facep->getTextureEntry();
|
||||
if(te)
|
||||
{
|
||||
LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL;
|
||||
LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_DISCARD) : NULL;
|
||||
if(!tex && te->getID() != mID)//try parcel media.
|
||||
{
|
||||
tex = gTextureList.findImage(mID, TEX_LIST_STANDARD);
|
||||
tex = gTextureList.findImage(mID, TEX_LIST_DISCARD);
|
||||
}
|
||||
if(!tex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,18 +72,20 @@ static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMAGES("Process Images");
|
|||
|
||||
ETexListType get_element_type(S32 priority)
|
||||
{
|
||||
if (priority == LLViewerFetchedTexture::BOOST_ICON)
|
||||
// don't discard flag can be used in some cases, but it usually is not set yet
|
||||
if (priority == LLViewerFetchedTexture::BOOST_ICON
|
||||
|| priority == LLViewerFetchedTexture::BOOST_UI)
|
||||
{
|
||||
return TEX_LIST_SCALE;
|
||||
return TEX_LIST_UI;
|
||||
}
|
||||
return TEX_LIST_STANDARD;
|
||||
return TEX_LIST_DISCARD;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLTextureKey::LLTextureKey()
|
||||
: textureId(LLUUID::null),
|
||||
textureType(TEX_LIST_STANDARD)
|
||||
textureType(TEX_LIST_DISCARD)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -589,7 +591,7 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
|
|||
|
||||
void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector<LLViewerFetchedTexture*> &output)
|
||||
{
|
||||
LLTextureKey search_key(image_id, TEX_LIST_STANDARD);
|
||||
LLTextureKey search_key(image_id, TEX_LIST_DISCARD);
|
||||
uuid_map_t::iterator iter = mUUIDMap.lower_bound(search_key);
|
||||
while (iter != mUUIDMap.end() && iter->first.textureId == image_id)
|
||||
{
|
||||
|
|
@ -1595,14 +1597,14 @@ void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **
|
|||
LLUUID image_id;
|
||||
msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, image_id);
|
||||
|
||||
LLViewerFetchedTexture* image = gTextureList.findImage( image_id, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture* image = gTextureList.findImage( image_id, TEX_LIST_DISCARD);
|
||||
if( image )
|
||||
{
|
||||
LL_WARNS() << "Image not in db" << LL_ENDL;
|
||||
image->setIsMissingAsset();
|
||||
}
|
||||
|
||||
image = gTextureList.findImage(image_id, TEX_LIST_SCALE);
|
||||
image = gTextureList.findImage(image_id, TEX_LIST_UI);
|
||||
if (image)
|
||||
{
|
||||
LL_WARNS() << "Icon not in db" << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ typedef void (*LLImageCallback)(BOOL success,
|
|||
|
||||
enum ETexListType
|
||||
{
|
||||
TEX_LIST_STANDARD = 0,
|
||||
TEX_LIST_SCALE // images that will be scaled, they should not be mixed up with regular images
|
||||
TEX_LIST_DISCARD = 0,
|
||||
TEX_LIST_UI
|
||||
};
|
||||
|
||||
struct LLTextureKey
|
||||
|
|
|
|||
|
|
@ -1992,7 +1992,7 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
|
|||
uuid == IMG_INVISIBLE)
|
||||
{
|
||||
// Should already exist, don't need to find it on sim or baked-texture host.
|
||||
result = gTextureList.findImage(uuid, TEX_LIST_STANDARD);
|
||||
result = gTextureList.findImage(uuid, TEX_LIST_DISCARD);
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
|
|
@ -4313,7 +4313,7 @@ bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const
|
|||
{
|
||||
for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_DISCARD);
|
||||
if (imagep && imagep->getDiscardLevel()!=0)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -4385,7 +4385,7 @@ S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set<LLUUID>& ids)
|
|||
S32Bytes result(0);
|
||||
for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_DISCARD);
|
||||
if (imagep)
|
||||
{
|
||||
result += imagep->getTextureMemory();
|
||||
|
|
@ -4473,7 +4473,7 @@ void LLVOAvatar::releaseOldTextures()
|
|||
{
|
||||
if (new_texture_ids.find(*it) == new_texture_ids.end())
|
||||
{
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD);
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_DISCARD);
|
||||
if (imagep)
|
||||
{
|
||||
current_texture_mem += imagep->getTextureMemory();
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ $/LicenseInfo$
|
|||
"""
|
||||
import sys
|
||||
import os.path
|
||||
import shutil
|
||||
import errno
|
||||
import re
|
||||
import tarfile
|
||||
|
|
@ -855,14 +856,17 @@ class Darwin_i386_Manifest(ViewerManifest):
|
|||
# This code constructs a relative path from the
|
||||
# target framework folder back to the location of the symlink.
|
||||
# It needs to be relative so that the symlink still works when
|
||||
# (as is normal) the user moves the app bunlde out of the DMG
|
||||
# (as is normal) the user moves the app bundle out of the DMG
|
||||
# and into the /Applications folder. Note we also call 'raise'
|
||||
# to terminate the process if we get an error since without
|
||||
# this symlink, Second Life web media can't possibly work.
|
||||
# Real Framework folder:
|
||||
# Second Life.app/Contents/Frameworks/Chromium Embedded Framework.framework/
|
||||
# Location of symlink and why it'ds relavie
|
||||
# Location of symlink and why it'ds relative
|
||||
# Second Life.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework/
|
||||
# Real Frameworks folder, with the symlink inside the bundled SLPlugin.app (and why it's relative)
|
||||
# <top level>.app/Contents/Frameworks/Chromium Embedded Framework.framework/
|
||||
# <top level>.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework ->
|
||||
frameworkpath = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, "Frameworks", "Chromium Embedded Framework.framework")
|
||||
try:
|
||||
symlinkf(frameworkpath, pluginframeworkpath)
|
||||
|
|
@ -872,10 +876,6 @@ class Darwin_i386_Manifest(ViewerManifest):
|
|||
|
||||
self.end_prefix("Contents")
|
||||
|
||||
# fix up media_plugin.dylib so it knows where to look for CEF files it needs
|
||||
self.run_command('install_name_tool -change "@executable_path/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "%(config)s/Second Life.app/Contents/Resources/llplugin/media_plugin_cef.dylib"' %
|
||||
{ 'config' : self.args['configuration'] })
|
||||
|
||||
# NOTE: the -S argument to strip causes it to keep enough info for
|
||||
# annotated backtraces (i.e. function names in the crash log). 'strip' with no
|
||||
# arguments yields a slightly smaller binary but makes crash logs mostly useless.
|
||||
|
|
@ -1247,12 +1247,33 @@ def symlinkf(src, dst):
|
|||
# file, but that strategy doesn't work so well if we don't have
|
||||
# permissions to remove it. Check to see if it's already the
|
||||
# symlink we want, which is the usual reason for EEXIST.
|
||||
if not (os.path.islink(dst) and os.readlink(dst) == src):
|
||||
# Here either dst isn't a symlink or it's the wrong symlink.
|
||||
# Remove and recreate. Caller will just have to deal with any
|
||||
# exceptions at this stage.
|
||||
elif os.path.islink(dst):
|
||||
if os.readlink(dst) == src:
|
||||
# the requested link already exists
|
||||
pass
|
||||
else:
|
||||
# dst is the wrong symlink; attempt to remove and recreate it
|
||||
os.remove(dst)
|
||||
os.symlink(src, dst)
|
||||
elif os.path.isdir(dst):
|
||||
print "Requested symlink (%s) exists but is a directory; replacing" % dst
|
||||
shutil.rmtree(dst)
|
||||
os.symlink(src, dst)
|
||||
elif os.path.exists(dst):
|
||||
print "Requested symlink (%s) exists but is a file; replacing" % dst
|
||||
os.remove(dst)
|
||||
os.symlink(src, dst)
|
||||
else:
|
||||
# see if the problem is that the parent directory does not exist
|
||||
# and try to explain what is missing
|
||||
(parent, tail) = os.path.split(dst)
|
||||
while not os.path.exists(parent):
|
||||
(parent, tail) = os.path.split(parent)
|
||||
if tail:
|
||||
raise Exception("Requested symlink (%s) cannot be created because %s does not exist"
|
||||
% os.path.join(parent, tail))
|
||||
else:
|
||||
raise
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue