Introduce scm::ng::root_for_path

Also change SCM implementation so that it doesn’t use objects with automatic storage, as the objects may be accessed from threads, which may run after objects with automatic storage has been destroyed.
This commit is contained in:
Allan Odgaard
2013-02-03 10:48:38 +01:00
parent ef8e1a7597
commit e599bb7379
3 changed files with 60 additions and 16 deletions

View File

@@ -72,8 +72,9 @@ _Iter prune_path_children (_Iter it, _Iter last)
+ (NSURL*)scmURLWithPath:(NSString*)aPath
{
if(scm::info_ptr info = scm::info([aPath fileSystemRepresentation]))
return [NSURL URLWithString:[NSString stringWithCxxString:"scm://localhost" + encode::url_part(info->path(), "/") + "/"]];
std::string root = scm::ng::root_for_path([aPath fileSystemRepresentation]);
if(root != NULL_STR)
return [NSURL URLWithString:[NSString stringWithCxxString:"scm://localhost" + encode::url_part(root, "/") + "/"]];
return [NSURL fileURLWithPath:aPath];
}

View File

@@ -220,27 +220,41 @@ namespace scm { namespace ng
// = Other =
// =========
static std::map<std::string, shared_info_weak_ptr> cache;
shared_info_ptr find_shared_info_for (std::string const& path)
static std::map<std::string, shared_info_weak_ptr>& cache ()
{
static scm::driver_t* const drivers[] = { scm::git_driver(), scm::hg_driver(), scm::p4_driver(), scm::svn_driver() };
static auto res = new std::map<std::string, shared_info_weak_ptr>;
return *res;
}
static dispatch_queue_t cache_access_queue ()
{
static dispatch_queue_t res = dispatch_queue_create("org.textmate.scm.info-cache", DISPATCH_QUEUE_SERIAL);
return res;
}
static std::vector<driver_t*> const& drivers ()
{
static auto const res = new std::vector<driver_t*>{ scm::git_driver(), scm::hg_driver(), scm::p4_driver(), scm::svn_driver() };
return *res;
}
static shared_info_ptr find_shared_info_for (std::string const& path)
{
for(std::string cwd = path; cwd != "/"; cwd = path::parent(cwd))
{
auto it = cache.find(cwd);
if(it != cache.end())
auto it = cache().find(cwd);
if(it != cache().end())
{
if(shared_info_ptr res = it->second.lock())
return res;
}
for(driver_t* driver : drivers)
for(driver_t* driver : drivers())
{
if(driver && driver->has_info_for_directory(cwd))
{
shared_info_ptr res(new shared_info_t(cwd, driver));
cache[cwd] = res;
cache()[cwd] = res;
return res;
}
}
@@ -248,6 +262,36 @@ namespace scm { namespace ng
return shared_info_ptr();
}
std::string root_for_path (std::string const& path)
{
if(path == NULL_STR || path == "" || path[0] != '/')
return NULL_STR;
__block std::string res = NULL_STR;
dispatch_sync(cache_access_queue(), ^{
for(std::string cwd = path; res == NULL_STR && cwd != "/"; cwd = path::parent(cwd))
{
auto it = cache().find(cwd);
if(it != cache().end())
{
res = cwd;
}
else
{
for(driver_t* driver : drivers())
{
if(driver && driver->has_info_for_directory(cwd))
{
res = cwd;
break;
}
}
}
}
});
return res;
}
info_ptr info (std::string path)
{
if(path == NULL_STR || path == "" || path[0] != '/')
@@ -255,11 +299,9 @@ namespace scm { namespace ng
info_ptr res(new info_t(path));
static dispatch_queue_t queue = dispatch_queue_create("org.textmate.scm.info-cache", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
auto it = cache.find(path);
if(it != cache.end())
dispatch_sync(cache_access_queue(), ^{
auto it = cache().find(path);
if(it != cache().end())
{
if(shared_info_ptr sharedInfo = it->second.lock())
res->set_shared_info(sharedInfo);
@@ -268,7 +310,7 @@ namespace scm { namespace ng
if(res->dry())
{
dispatch_async(queue, ^{
dispatch_async(cache_access_queue(), ^{
if(shared_info_ptr info = find_shared_info_for(path))
{
dispatch_async(dispatch_get_main_queue(), ^{

View File

@@ -36,6 +36,7 @@ namespace scm { namespace ng
shared_info_ptr _shared_info;
};
PUBLIC std::string root_for_path (std::string const& path);
PUBLIC info_ptr info (std::string path);
} /* ng */ } /* scm */