File src/cmds/SetCmd.cpp changed (mode: 100644) (index c62bf37..b197b5e) |
... |
... |
SetCmd::run(Project &project, const std::vector<std::string> &args) |
121 |
121 |
} |
} |
122 |
122 |
|
|
123 |
123 |
const std::string current = append ? std::string() : fields[key]; |
const std::string current = append ? std::string() : fields[key]; |
124 |
|
if (boost::optional<std::string> v = editValue(key, value, current)) { |
|
|
124 |
|
if (value == "-") { |
|
125 |
|
boost::optional<std::string> v = editValue(key, current); |
|
126 |
|
if (!v) { |
|
127 |
|
err() << "Failed to prompt for value of key \"" |
|
128 |
|
<< key << "\"\n"; |
|
129 |
|
return EXIT_FAILURE; |
|
130 |
|
} |
125 |
131 |
value = std::move(*v); |
value = std::move(*v); |
126 |
132 |
} |
} |
127 |
133 |
|
|
File src/integration.cpp changed (mode: 100644) (index a20e35c..ae6c5eb) |
... |
... |
getTerminalSize() |
296 |
296 |
} |
} |
297 |
297 |
|
|
298 |
298 |
boost::optional<std::string> |
boost::optional<std::string> |
299 |
|
editValue(const std::string &key, const std::string &value, |
|
300 |
|
const std::string ¤t) |
|
|
299 |
|
editValue(const std::string &key, const std::string ¤t) |
301 |
300 |
{ |
{ |
302 |
|
if (value != "-") { |
|
303 |
|
return {}; |
|
304 |
|
} |
|
305 |
|
|
|
306 |
|
// Create name for temporary file name and the file itself. |
|
|
301 |
|
// Generate name of a temporary file and write the file. |
307 |
302 |
TempFile tmpFile("buf"); |
TempFile tmpFile("buf"); |
308 |
303 |
writeBufferFile(tmpFile, key, current); |
writeBufferFile(tmpFile, key, current); |
309 |
304 |
|
|
310 |
305 |
if (!editBufferFile(tmpFile)) { |
if (!editBufferFile(tmpFile)) { |
311 |
|
return current; |
|
|
306 |
|
return {}; |
312 |
307 |
} |
} |
313 |
308 |
|
|
314 |
309 |
return readEditedValue(tmpFile); |
return readEditedValue(tmpFile); |
File src/integration.hpp changed (mode: 100644) (index 0461bb0..8f12b4c) |
... |
... |
private: |
60 |
60 |
* @brief Edits value if user requested for it. |
* @brief Edits value if user requested for it. |
61 |
61 |
* |
* |
62 |
62 |
* @param key Key (name of the value). |
* @param key Key (name of the value). |
63 |
|
* @param value New value (can be special value, which means "edit"). |
|
64 |
63 |
* @param current Current value to be edited. |
* @param current Current value to be edited. |
65 |
64 |
* |
* |
66 |
65 |
* @returns Nothing if @p value can be used as is, otherwise new value. |
* @returns Nothing if @p value can be used as is, otherwise new value. |
67 |
66 |
*/ |
*/ |
68 |
67 |
boost::optional<std::string> editValue(const std::string &key, |
boost::optional<std::string> editValue(const std::string &key, |
69 |
|
const std::string &value, |
|
70 |
68 |
const std::string ¤t); |
const std::string ¤t); |
71 |
69 |
|
|
72 |
70 |
/** |
/** |
File tests/cmds/AddCmd.cpp changed (mode: 100644) (index f170aa8..0976a94) |
... |
... |
TEST_CASE("Addition on new item", "[cmds][add]") |
148 |
148 |
REQUIRE(out.str() == "Created item: fYP\n"); |
REQUIRE(out.str() == "Created item: fYP\n"); |
149 |
149 |
REQUIRE(err.str() == std::string()); |
REQUIRE(err.str() == std::string()); |
150 |
150 |
} |
} |
|
151 |
|
|
|
152 |
|
SECTION("Item is not created on failed external editing") |
|
153 |
|
{ |
|
154 |
|
static char editor_env[] = "EDITOR=wrong-command >>"; |
|
155 |
|
putenv(editor_env); |
|
156 |
|
|
|
157 |
|
boost::optional<int> exitCode = cmd->run(*prj, |
|
158 |
|
{ "title:", "title", |
|
159 |
|
"status:", "-", |
|
160 |
|
"author:", "me" }); |
|
161 |
|
REQUIRE(exitCode); |
|
162 |
|
REQUIRE(*exitCode == EXIT_FAILURE); |
|
163 |
|
|
|
164 |
|
REQUIRE(out.str() == std::string()); |
|
165 |
|
REQUIRE(err.str() != std::string()); |
|
166 |
|
} |
151 |
167 |
} |
} |
152 |
168 |
|
|
153 |
169 |
TEST_CASE("Completion of first key name on addition", "[cmds][add][completion]") |
TEST_CASE("Completion of first key name on addition", "[cmds][add][completion]") |
File tests/cmds/ConfigCmd.cpp changed (mode: 100644) (index 07bee4f..7fa4538) |
... |
... |
TEST_CASE("Config allows external editing", "[cmds][config][integration]") |
120 |
120 |
REQUIRE(prj->getConfig(true).get("value") == "new-value"); |
REQUIRE(prj->getConfig(true).get("value") == "new-value"); |
121 |
121 |
} |
} |
122 |
122 |
|
|
|
123 |
|
TEST_CASE("Config is not updated on failed external editing", |
|
124 |
|
"[cmds][config][integration]") |
|
125 |
|
{ |
|
126 |
|
std::unique_ptr<Project> prj = Tests::makeProject(); |
|
127 |
|
|
|
128 |
|
std::ostringstream out, err; |
|
129 |
|
Tests::setStreams(out, err); |
|
130 |
|
|
|
131 |
|
static char editor_env[] = "EDITOR=wrong-command >>"; |
|
132 |
|
putenv(editor_env); |
|
133 |
|
|
|
134 |
|
Config &cfg = prj->getConfig(true); |
|
135 |
|
|
|
136 |
|
cfg.set("a", "olda"); |
|
137 |
|
cfg.set("b", "oldb"); |
|
138 |
|
cfg.set("c", "oldc"); |
|
139 |
|
|
|
140 |
|
Command *const cmd = Commands::get("config"); |
|
141 |
|
boost::optional<int> exitCode = cmd->run(*prj, { "a:", "newa", |
|
142 |
|
"b:", "-", |
|
143 |
|
"c:", "newc" }); |
|
144 |
|
REQUIRE(exitCode); |
|
145 |
|
REQUIRE(*exitCode == EXIT_FAILURE); |
|
146 |
|
|
|
147 |
|
REQUIRE(out.str() == std::string()); |
|
148 |
|
REQUIRE(err.str() != std::string()); |
|
149 |
|
|
|
150 |
|
REQUIRE(cfg.get("a") == "olda"); |
|
151 |
|
REQUIRE(cfg.get("b") == "oldb"); |
|
152 |
|
REQUIRE(cfg.get("c") == "oldc"); |
|
153 |
|
} |
|
154 |
|
|
123 |
155 |
TEST_CASE("Global configuration is processed", "[cmds][config]") |
TEST_CASE("Global configuration is processed", "[cmds][config]") |
124 |
156 |
{ |
{ |
125 |
157 |
Command *const cmd = Commands::get("config"); |
Command *const cmd = Commands::get("config"); |
File tests/cmds/SetCmd.cpp changed (mode: 100644) (index deb77c3..29936e3) |
... |
... |
TEST_CASE("Set allows external editing", "[cmds][set][integration]") |
104 |
104 |
REQUIRE(storage.get("id").getValue("bug_number") == "22new-value"); |
REQUIRE(storage.get("id").getValue("bug_number") == "22new-value"); |
105 |
105 |
} |
} |
106 |
106 |
|
|
|
107 |
|
TEST_CASE("Nothing is set on failed external editing", |
|
108 |
|
"[cmds][set][integration]") |
|
109 |
|
{ |
|
110 |
|
std::unique_ptr<Project> prj = Tests::makeProject(); |
|
111 |
|
Storage &storage = prj->getStorage(); |
|
112 |
|
|
|
113 |
|
Item item = Tests::makeItem("id"); |
|
114 |
|
item.setValue("title", "oldtitle"); |
|
115 |
|
item.setValue("author", "someone"); |
|
116 |
|
|
|
117 |
|
Tests::storeItem(storage, std::move(item)); |
|
118 |
|
|
|
119 |
|
std::ostringstream out, err; |
|
120 |
|
Tests::setStreams(out, err); |
|
121 |
|
|
|
122 |
|
static char editor_env[] = "EDITOR=wrong-command >>"; |
|
123 |
|
putenv(editor_env); |
|
124 |
|
|
|
125 |
|
Command *const cmd = Commands::get("set"); |
|
126 |
|
boost::optional<int> exitCode = cmd->run(*prj, { "id", |
|
127 |
|
"title:", "title", |
|
128 |
|
"status:", "-", |
|
129 |
|
"author:", "me" }); |
|
130 |
|
REQUIRE(exitCode); |
|
131 |
|
REQUIRE(*exitCode == EXIT_FAILURE); |
|
132 |
|
|
|
133 |
|
REQUIRE(out.str() == std::string()); |
|
134 |
|
REQUIRE(err.str() != std::string()); |
|
135 |
|
|
|
136 |
|
REQUIRE(storage.get("id").getValue("title") == "oldtitle"); |
|
137 |
|
REQUIRE(storage.get("id").getValue("status") == std::string()); |
|
138 |
|
REQUIRE(storage.get("id").getValue("author") == "someone"); |
|
139 |
|
} |
|
140 |
|
|
107 |
141 |
TEST_CASE("Item is changed successfully", "[cmds][set]") |
TEST_CASE("Item is changed successfully", "[cmds][set]") |
108 |
142 |
{ |
{ |
109 |
143 |
std::unique_ptr<Project> prj = Tests::makeProject(); |
std::unique_ptr<Project> prj = Tests::makeProject(); |
File tests/integration.cpp changed (mode: 100644) (index adb6cb4..cbe8599) |
... |
... |
TEST_CASE("On failure curent value is returned.", "[integration]") |
26 |
26 |
static char editor_env[] = "EDITOR=wrong-command >>"; |
static char editor_env[] = "EDITOR=wrong-command >>"; |
27 |
27 |
putenv(editor_env); |
putenv(editor_env); |
28 |
28 |
|
|
29 |
|
boost::optional<std::string> val = editValue("key", "-", "current"); |
|
30 |
|
REQUIRE(val); |
|
31 |
|
REQUIRE(*val == "current"); |
|
|
29 |
|
boost::optional<std::string> val = editValue("key", "current"); |
|
30 |
|
REQUIRE_FALSE(val); |
32 |
31 |
} |
} |