remove command, which supports dry runs (so does create)
This commit is contained in:
parent
0adbe5e0d1
commit
bfffa2dd7f
@ -13,6 +13,7 @@ namespace cellar {
|
|||||||
|
|
||||||
extern bottles::Bottle active_bottle;
|
extern bottles::Bottle active_bottle;
|
||||||
|
|
||||||
|
extern bool dryrun;
|
||||||
extern bool verbose;
|
extern bool verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,14 @@ using namespace std;
|
|||||||
|
|
||||||
namespace cellar {
|
namespace cellar {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
|
typedef void (*CopyCallbackFunc)(string,string);
|
||||||
|
typedef void (*RemoveCallbackFunc)(string);
|
||||||
extern vector<string> listdir(string path);
|
extern vector<string> listdir(string path);
|
||||||
|
|
||||||
extern bool recursive_copy(string, string);
|
extern bool recursive_copy(string, string);
|
||||||
extern bool recursive_remove(string);
|
extern bool recursive_remove(string);
|
||||||
|
extern bool recursive_copy(string, string, CopyCallbackFunc);
|
||||||
|
extern bool recursive_remove(string, RemoveCallbackFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,3 +3,4 @@ active print_active_bottle Get the currently active WINE bottle.
|
|||||||
activate switch_active_bottle Switch the active WINE bottle.
|
activate switch_active_bottle Switch the active WINE bottle.
|
||||||
config config_command Change configuration options.
|
config config_command Change configuration options.
|
||||||
create create_bottle Create a new WINE bottle.
|
create create_bottle Create a new WINE bottle.
|
||||||
|
remove remove_bottle Remove a WINE bottle.
|
||||||
|
45
src/bottles/remove.cpp
Normal file
45
src/bottles/remove.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/filesystem/operations.hpp>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "bottles.hpp"
|
||||||
|
#include "internal/bottles.hpp"
|
||||||
|
#include "fs.hpp"
|
||||||
|
#include "output.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cellar;
|
||||||
|
|
||||||
|
void cellar::bottles::remove_bottle(int argc, vector<string> argv) {
|
||||||
|
string homepath = getenv("HOME");
|
||||||
|
string bottlechoice = argv[1];
|
||||||
|
string fullbottlepath;
|
||||||
|
if (bottlechoice.substr(0,1) == "/" || bottlechoice.substr(0,1) == ".") { // absolute or relative path
|
||||||
|
fullbottlepath = bottlechoice;
|
||||||
|
} else if (bottlechoice.substr(0,1) == "~") { // "absolute" path in home directory, not expanded by the shell for some reason (i've seen some shit)
|
||||||
|
// this is a naive replacement and will fail if the user tries something like ~nick/.wine
|
||||||
|
// i'm figuring at that point if you're doing that, you'll also recognize if your shell
|
||||||
|
// isn't actually expanding your path...
|
||||||
|
bottlechoice.replace(0,1,getenv("HOME"));
|
||||||
|
// or at least you'll think to use verbose mode to make sure it's loading the right directory
|
||||||
|
output::warning("your shell didn't expand your given path properly, doing a naive replacement", true);
|
||||||
|
fullbottlepath = bottlechoice;
|
||||||
|
} else {
|
||||||
|
if (bottlechoice.substr(0,6) == ".wine.") {
|
||||||
|
output::statement("tip: cellar can add the \".wine.\" prefix automatically");
|
||||||
|
bottlechoice.replace(0,6,"");
|
||||||
|
}
|
||||||
|
|
||||||
|
fullbottlepath = homepath + "/.wine." + bottlechoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boost::filesystem::exists(fullbottlepath)) {
|
||||||
|
output::error(bottlechoice + " doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::recursive_remove(fullbottlepath);
|
||||||
|
}
|
@ -28,6 +28,7 @@ using namespace std;
|
|||||||
using namespace cellar;
|
using namespace cellar;
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
bool cellar::dryrun;
|
||||||
bool cellar::verbose;
|
bool cellar::verbose;
|
||||||
|
|
||||||
bottles::Bottle cellar::active_bottle;
|
bottles::Bottle cellar::active_bottle;
|
||||||
@ -52,6 +53,9 @@ int main(int argc, char* argv[]) {
|
|||||||
TCLAP::ValueArg<string> bottlearg("b", "bottle", "Use a wine bottle other than the one at ~/.wine", false, "", "bottle");
|
TCLAP::ValueArg<string> bottlearg("b", "bottle", "Use a wine bottle other than the one at ~/.wine", false, "", "bottle");
|
||||||
cmdparse.add(bottlearg);
|
cmdparse.add(bottlearg);
|
||||||
|
|
||||||
|
TCLAP::SwitchArg dryrunarg("d", "dry-run", "Doesn't actually do anything");
|
||||||
|
cmdparse.add(dryrunarg);
|
||||||
|
|
||||||
TCLAP::SwitchArg verbosearg("v", "verbose", "Enables extra output");
|
TCLAP::SwitchArg verbosearg("v", "verbose", "Enables extra output");
|
||||||
cmdparse.add(verbosearg);
|
cmdparse.add(verbosearg);
|
||||||
|
|
||||||
@ -63,6 +67,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
cmdparse.parse(argc, argv);
|
cmdparse.parse(argc, argv);
|
||||||
|
|
||||||
|
dryrun = dryrunarg.getValue();
|
||||||
verbose = verbosearg.getValue();
|
verbose = verbosearg.getValue();
|
||||||
|
|
||||||
// BULLSHIT: trying to use str.format on this string causes bizarre compiler errors
|
// BULLSHIT: trying to use str.format on this string causes bizarre compiler errors
|
||||||
|
54
src/fs.cpp
54
src/fs.cpp
@ -5,13 +5,22 @@
|
|||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "cellar.hpp"
|
||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
#include "output.hpp"
|
#include "output.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
using namespace cellar;
|
||||||
|
using namespace fs;
|
||||||
|
|
||||||
vector<string> cellar::fs::listdir(string path) {
|
// these are not necessarily the final function signatures for callbacks
|
||||||
|
// this only exists so i don't have to come back and do the ductwork for
|
||||||
|
// callback functionality later
|
||||||
|
void cbnull_copy(string src, string dst) { return; }
|
||||||
|
void cbnull_remove(string src) { return; }
|
||||||
|
|
||||||
|
vector<string> fs::listdir(string path) {
|
||||||
vector<string> result;
|
vector<string> result;
|
||||||
filesystem::path cwd(path);
|
filesystem::path cwd(path);
|
||||||
filesystem::directory_iterator iter_end;
|
filesystem::directory_iterator iter_end;
|
||||||
@ -24,42 +33,61 @@ vector<string> cellar::fs::listdir(string path) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cellar::fs::recursive_copy(string src, string dst) {
|
bool fs::recursive_copy(string src, string dst, CopyCallbackFunc callback) {
|
||||||
if (!filesystem::exists(dst)) {
|
if (!filesystem::exists(dst)) {
|
||||||
bool success = filesystem::create_directory(dst);
|
if (dryrun) { output::statement("mkdir: " + dst); }
|
||||||
if (!success) { return false; }
|
else {
|
||||||
|
bool success = filesystem::create_directory(dst);
|
||||||
|
if (!success) { return false; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (string itemrel : cellar::fs::listdir(src)) {
|
for (string itemrel : listdir(src)) {
|
||||||
string itemabs = src + "/" + itemrel;
|
string itemabs = src + "/" + itemrel;
|
||||||
string targetabs = dst + "/" + itemrel;
|
string targetabs = dst + "/" + itemrel;
|
||||||
|
|
||||||
auto itemstat = filesystem::symlink_status(itemabs);
|
auto itemstat = filesystem::symlink_status(itemabs);
|
||||||
|
|
||||||
if (filesystem::is_directory(itemstat)) { recursive_copy(itemabs, targetabs); }
|
if (filesystem::is_directory(itemstat)) { recursive_copy(itemabs, targetabs, callback); }
|
||||||
else if (filesystem::is_symlink(itemstat)) {
|
else if (filesystem::is_symlink(itemstat)) {
|
||||||
auto symlinkpath = filesystem::read_symlink(itemabs);
|
auto symlinkpath = filesystem::read_symlink(itemabs);
|
||||||
filesystem::create_symlink(symlinkpath, targetabs);
|
if (dryrun) { output::statement("symlink: " + symlinkpath.native() + " => " + targetabs); }
|
||||||
|
else { filesystem::create_symlink(symlinkpath, targetabs); }
|
||||||
}
|
}
|
||||||
else { filesystem::copy(itemabs, targetabs); }
|
else {
|
||||||
|
if (dryrun) { output::statement("copy: " + itemabs + " => " + targetabs); }
|
||||||
|
else { filesystem::copy(itemabs, targetabs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(itemabs, targetabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cellar::fs::recursive_remove(string target) {
|
bool fs::recursive_copy(string src, string dst) { return recursive_copy(src, dst, cbnull_copy); }
|
||||||
|
|
||||||
|
bool fs::recursive_remove(string target, RemoveCallbackFunc callback) {
|
||||||
if (!filesystem::exists(target)) { return false; }
|
if (!filesystem::exists(target)) { return false; }
|
||||||
|
|
||||||
for (string itemrel : cellar::fs::listdir(target)) {
|
for (string itemrel : listdir(target)) {
|
||||||
string itemabs = target + "/" + itemrel;
|
string itemabs = target + "/" + itemrel;
|
||||||
|
|
||||||
auto itemstat = filesystem::symlink_status(itemabs);
|
auto itemstat = filesystem::symlink_status(itemabs);
|
||||||
|
|
||||||
if (filesystem::is_directory(itemstat)) { recursive_remove(itemabs); }
|
if (filesystem::is_directory(itemstat)) { recursive_remove(itemabs, callback); }
|
||||||
else { filesystem::remove(itemabs); }
|
else {
|
||||||
|
if (dryrun) { output::error("rm: " + itemabs); }
|
||||||
|
else { filesystem::remove(itemabs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(itemabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem::remove(target);
|
if (dryrun) { output::error("rm: " + target); }
|
||||||
|
else { filesystem::remove(target); }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fs::recursive_remove(string target) { return recursive_remove(target, cbnull_remove); }
|
||||||
|
Loading…
Reference in New Issue
Block a user