mirror of
https://github.com/textmate/textmate.git
synced 2026-01-23 21:57:54 -05:00
Majority of the edits done using the following ruby script:
def update_loops(src)
dst, cnt = '', 0
block_indent, variable = nil, nil
src.each_line do |line|
if block_indent
if line =~ /^#{block_indent}([{}\t])|^\t*$/
block_indent = nil if $1 == '}'
line = line.gsub(%r{ ([^a-z>]) \(\*#{variable}\) | \*#{variable}\b | \b#{variable}(->) }x) do
$1.to_s + variable + ($2 == "->" ? "." : "")
end
else
block_indent = nil
end
elsif line =~ /^(\t*)c?iterate\((\w+), (?!diacritics::make_range)(.*\))$/
block_indent, variable = $1, $2
line = "#$1for(auto const& #$2 : #$3\n"
cnt += 1
end
dst << line
end
return dst, cnt
end
paths.each do |path|
src = IO.read(path)
cnt = 1
while cnt != 0
src, cnt = update_loops(src)
STDERR << "#{path}: #{cnt}\n"
end
File.open(path, "w") { |io| io << src }
end
242 lines
5.9 KiB
C++
242 lines
5.9 KiB
C++
#include "io.h"
|
||
#include "entries.h"
|
||
#include <oak/debug.h>
|
||
|
||
OAK_DEBUG_VAR(IO_Info);
|
||
OAK_DEBUG_VAR(IO_Failure);
|
||
|
||
// ====================
|
||
// = Helper Functions =
|
||
// ====================
|
||
|
||
static bool send_move_request_to_auth_server (std::string const& src, std::string const& dst, bool overwrite)
|
||
{
|
||
D(DBF_IO_Failure, bug("request requires root (%s → %s)\n", src.c_str(), dst.c_str()););
|
||
ASSERT(false);
|
||
return false;
|
||
}
|
||
|
||
static bool is_copyable_dir (std::string const& path)
|
||
{
|
||
if(access(path.c_str(), X_OK) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("unable to read dir ‘%s’: %s\n", path.c_str(), strerror(errno)););
|
||
return false;
|
||
}
|
||
|
||
bool res = true;
|
||
for(auto const& it : path::entries(path))
|
||
{
|
||
std::string const& newSrc = path::join(path, it->d_name);
|
||
if(it->d_type == DT_REG)
|
||
{
|
||
if(access(newSrc.c_str(), R_OK) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("unable to read file ‘%s’: %s\n", newSrc.c_str(), strerror(errno)););
|
||
res = false;
|
||
}
|
||
}
|
||
else if(it->d_type == DT_DIR)
|
||
{
|
||
res = is_copyable_dir(newSrc);
|
||
}
|
||
else if(it->d_type == DT_LNK)
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
D(DBF_IO_Failure, bug("unknown file type: %s (%d)\n", newSrc.c_str(), it->d_type););
|
||
res = false;
|
||
}
|
||
|
||
if(!res)
|
||
break;
|
||
}
|
||
return res;
|
||
}
|
||
|
||
static bool is_copyable (std::string const& path)
|
||
{
|
||
struct stat buf;
|
||
if(lstat(path.c_str(), &buf) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("stat(\"%s\"): %s\n", path.c_str(), strerror(errno)););
|
||
}
|
||
else if(S_ISDIR(buf.st_mode))
|
||
{
|
||
return is_copyable_dir(path);
|
||
}
|
||
else if(S_ISLNK(buf.st_mode) || access(path.c_str(), R_OK) == 0)
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
D(DBF_IO_Failure, bug("unable to read file ‘%s’: %s\n", path.c_str(), strerror(errno)););
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// ====================
|
||
// = Public Functions =
|
||
// ====================
|
||
|
||
namespace path
|
||
{
|
||
bool copy (std::string const& src, std::string const& dst)
|
||
{
|
||
D(DBF_IO_Info, bug("%s → %s\n", src.c_str(), dst.c_str()););
|
||
ASSERTF(path::exists(src), "%s\n", src.c_str());
|
||
ASSERTF(!path::exists(dst), "%s\n", dst.c_str());
|
||
|
||
if(copyfile(src.c_str(), dst.c_str(), NULL, COPYFILE_ALL | COPYFILE_NOFOLLOW_SRC) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("copyfile(\"%s\", \"%s\"): %s\n", src.c_str(), dst.c_str(), strerror(errno)););
|
||
return false;
|
||
}
|
||
|
||
bool res = true;
|
||
for(auto const& it : path::entries(src))
|
||
{
|
||
std::string const& newSrc = path::join(src, it->d_name);
|
||
std::string const& newDst = path::join(dst, it->d_name);
|
||
if(it->d_type == DT_DIR)
|
||
{
|
||
res = path::copy(newSrc, newDst) && res;
|
||
}
|
||
else if(it->d_type == DT_REG || it->d_type == DT_LNK)
|
||
{
|
||
if(copyfile(newSrc.c_str(), newDst.c_str(), NULL, COPYFILE_ALL | COPYFILE_NOFOLLOW_SRC) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("copyfile(\"%s\", \"%s\"): %s\n", newSrc.c_str(), newDst.c_str(), strerror(errno)););
|
||
res = false;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
D(DBF_IO_Failure, bug("skip unknown type: %s (%d)\n", newSrc.c_str(), it->d_type););
|
||
res = false;
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
bool move (std::string const& src, std::string const& dst, bool overwrite)
|
||
{
|
||
D(DBF_IO_Info, bug("%s → %s\n", src.c_str(), dst.c_str()););
|
||
|
||
std::string const& dst_parent = path::parent(dst);
|
||
std::string const& src_parent = path::parent(src);
|
||
bool src_exists DB_VAR = path::exists(src);
|
||
bool dst_exists = path::exists(dst);
|
||
|
||
ASSERT(src_exists);
|
||
|
||
if(dst_exists && !overwrite)
|
||
{
|
||
D(DBF_IO_Failure, bug("destination exists: %s (and overwrite was disabled)\n", dst.c_str()););
|
||
errno = EEXIST;
|
||
return false;
|
||
}
|
||
|
||
if(!path::make_dir(dst_parent))
|
||
{
|
||
D(DBF_IO_Failure, bug("unable to create destination directory: %s\n", dst_parent.c_str()););
|
||
return false;
|
||
}
|
||
|
||
dev_t src_device = path::device(src);
|
||
dev_t dst_device = path::device(dst_parent);
|
||
|
||
if(dst_exists)
|
||
{
|
||
if(!path::remove(dst))
|
||
{
|
||
D(DBF_IO_Failure, bug("unable to remove existing destionation ‘%s’: %s\n", dst.c_str(), strerror(errno)););
|
||
return false; // if errno == EACCES then send_move_request_to_auth_server()
|
||
}
|
||
}
|
||
|
||
// when src and dst are on the same device we don’t need to ensure that ‘is_copyable(src)’
|
||
if(!is_copyable(src) || !path::is_writable(src_parent) || !path::is_writable(dst_parent))
|
||
return send_move_request_to_auth_server(src, dst, overwrite);
|
||
|
||
if(src_device == dst_device)
|
||
{
|
||
if(::rename(src.c_str(), dst.c_str()) == 0)
|
||
return true;
|
||
D(DBF_IO_Failure, bug("rename(\"%s\", \"%s\"): %s\n", src.c_str(), dst.c_str(), strerror(errno)););
|
||
}
|
||
else
|
||
{
|
||
return path::copy(src, dst) && path::remove(src);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
static bool remove_dir (std::string const& path)
|
||
{
|
||
bool res = true;
|
||
for(auto const& it : path::entries(path))
|
||
{
|
||
std::string const& newSrc = path::join(path, it->d_name);
|
||
if(it->d_type == DT_DIR)
|
||
{
|
||
res = path::remove_dir(newSrc) && res;
|
||
}
|
||
else
|
||
{
|
||
if(unlink(newSrc.c_str()) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("failed to unlink ‘%s’: %s\n", newSrc.c_str(), strerror(errno)););
|
||
res = false;
|
||
}
|
||
else
|
||
{
|
||
D(DBF_IO_Info, bug("unlinked ‘%s’\n", newSrc.c_str()););
|
||
}
|
||
}
|
||
}
|
||
|
||
if(res && rmdir(path.c_str()) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("failed to rmdir ‘%s’: %s\n", path.c_str(), strerror(errno)););
|
||
res = false;
|
||
}
|
||
else
|
||
{
|
||
D(DBF_IO_Info, bug("removed directory ‘%s’\n", path.c_str()););
|
||
}
|
||
return res;
|
||
}
|
||
|
||
bool remove (std::string const& path)
|
||
{
|
||
D(DBF_IO_Info, bug("%s\n", path == NULL_STR ? "(null)" : path.c_str()););
|
||
if(path == NULL_STR)
|
||
return false;
|
||
|
||
struct stat buf;
|
||
if(lstat(path.c_str(), &buf) != 0)
|
||
{
|
||
D(DBF_IO_Failure, bug("stat(\"%s\"): %s\n", path.c_str(), strerror(errno)););
|
||
}
|
||
else if(S_ISDIR(buf.st_mode))
|
||
{
|
||
return path::remove_dir(path);
|
||
}
|
||
else if(unlink(path.c_str()) == 0)
|
||
{
|
||
D(DBF_IO_Info, bug("unlinked ‘%s’\n", path.c_str()););
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
D(DBF_IO_Failure, bug("failed to unlink ‘%s’: %s\n", path.c_str(), strerror(errno)););
|
||
}
|
||
return false;
|
||
}
|
||
|
||
} /* path */
|