Skip to content

Commit 427e64c

Browse files
committed
Initial init packages helpers.
1 parent 72358fa commit 427e64c

10 files changed

Lines changed: 333 additions & 143 deletions

File tree

cppan.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ local_settings:
1515
pvt.cppan.demo.sqlite3: 3
1616
pvt.cppan.demo.coruus.keccak_tiny_unrolled: singlefile
1717
pvt.cppan.demo.gnu.readline.readline: 7
18+

src/client/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ file(GLOB cppan_src "*")
1111
add_executable(client ${cppan_src})
1212
target_link_libraries(client common
1313
pvt.cppan.demo.boost.program_options
14+
pvt.cppan.demo.gnu.readline.readline
1415
)
1516

1617
set_target_properties(client PROPERTIES OUTPUT_NAME cppan)

src/client/init.cpp

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
* Copyright (C) 2016-2017, Egor Pugin
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "build.h"
18+
19+
#include <config.h>
20+
#include <database.h>
21+
22+
#include <readline/readline.h>
23+
#include <readline/history.h>
24+
25+
#include <iostream>
26+
27+
#include <conio.h>
28+
29+
char **character_name_completion(const char *, int, int);
30+
char *character_name_generator(const char *, int);
31+
int old_string = 0;
32+
String old_s;
33+
34+
int my_getc(FILE *f)
35+
{
36+
auto c = _getch();
37+
old_string = !is_valid_project_path_symbol(c) &&
38+
c != '\b' && c != '-';
39+
if (!old_string)
40+
{
41+
old_s = rl_line_buffer;
42+
if (c != '\b')
43+
old_s += c;
44+
else if (!old_s.empty())
45+
old_s.resize(old_s.size() - 1);
46+
}
47+
return c;
48+
}
49+
50+
void command_init(const Strings &args)
51+
{
52+
String project_type = "e";
53+
Project p;
54+
p.name = fs::current_path().filename().string();
55+
56+
auto readline = [](String &d)
57+
{
58+
String s;
59+
std::getline(std::cin, s);
60+
if (!s.empty())
61+
d = s;
62+
};
63+
64+
// interactive mode
65+
if (args.empty())
66+
{
67+
std::cout << "Enter project name [" << p.name << "]: ";
68+
readline(p.name);
69+
std::cout << "Enter project type (e - executable, l - library) [" << project_type << "]: ";
70+
readline(project_type);
71+
std::cout << "Add some dependencies (y/n) [n]: ";
72+
String add_deps;
73+
readline(add_deps);
74+
if (add_deps[0] == 'y')
75+
{
76+
std::cout << "Start entering dependencies' names. You could use TAB to list matching packages.\n";
77+
78+
rl_attempted_completion_function = character_name_completion;
79+
rl_completion_query_items = 50;
80+
//rl_editing_mode = 0; // vi mode
81+
//rl_getc_function = my_getc;
82+
//rl_variable_bind("show-mode-in-prompt", "1");
83+
while (auto buffer = ::readline("> "))
84+
{
85+
printf("You entered: %s\n", buffer);
86+
if (*buffer)
87+
add_history(buffer);
88+
free(buffer);
89+
}
90+
}
91+
}
92+
else
93+
{
94+
95+
}
96+
97+
if (project_type[0] == 'l')
98+
p.type = ProjectType::Library;
99+
100+
boost::system::error_code ec;
101+
auto root = fs::current_path();
102+
103+
// checks first
104+
if (fs::exists(root / p.name) ||
105+
fs::exists(root / p.name / "src") ||
106+
fs::exists(root / p.name / "include") ||
107+
fs::exists(root / p.name / "include" / p.name) ||
108+
fs::exists(root / p.name / "include" / p.name / (p.name + ".h")) ||
109+
fs::exists(root / p.name / "src" / (p.name + ".cpp")) ||
110+
0)
111+
throw std::runtime_error("One of the fs objects to be created already exist");
112+
113+
// create, no checks
114+
fs::create_directories(root / p.name / "src");
115+
if (p.type == ProjectType::Library)
116+
{
117+
fs::create_directories(root / p.name / "include" / p.name);
118+
write_file(root / p.name / "src" / (p.name + ".cpp"), "#include <" + p.name + "/" + p.name + ".h>\n\n");
119+
write_file(root / p.name / "include" / p.name / (p.name + ".h"), "//#include <something>\n\n");
120+
}
121+
else
122+
{
123+
write_file(root / p.name / "src" / (p.name + ".cpp"), "//#include <something>\n\n"
124+
"int main(int argc, char **argv)\n{\n return 0;\n}\n");
125+
}
126+
127+
p.root_directory = p.name;
128+
129+
yaml y;
130+
if (!fs::exists(CPPAN_FILENAME))
131+
{
132+
y = p.save();
133+
}
134+
else
135+
{
136+
auto orig = load_yaml_config(path(CPPAN_FILENAME));
137+
Config c;
138+
c.allow_relative_project_names = true;
139+
//c.allow_local_dependencies = true;
140+
c.load(orig);
141+
auto &projects = c.getProjects();
142+
if (projects.find(p.name) != projects.end())
143+
throw std::runtime_error("Project " + p.name + " already exists in the config");
144+
projects[p.name] = p;
145+
y = c.save();
146+
orig["projects"] = y["projects"];
147+
y = orig;
148+
}
149+
dump_yaml_config(CPPAN_FILENAME, y);
150+
151+
build(root);
152+
}
153+
154+
char **
155+
character_name_completion(const char *text, int start, int end)
156+
{
157+
rl_attempted_completion_over = 1;
158+
rl_completion_suppress_append = 1;
159+
if (*text == 0 && start)
160+
return nullptr;
161+
return rl_completion_matches(text, character_name_generator);
162+
}
163+
164+
char *
165+
character_name_generator(const char *text, int state)
166+
{
167+
static std::vector<String> spkgs;
168+
static size_t i;
169+
static String t;
170+
171+
auto read_packages = [](const String &s)
172+
{
173+
auto &pdb = getPackagesDatabase();
174+
auto pkgs = pdb.getMatchingPackages<std::unordered_set>(s);
175+
std::vector<String> spkgs;
176+
spkgs.reserve(pkgs.size());
177+
for (auto &pkg : pkgs)
178+
spkgs.push_back(pkg.toString());
179+
return spkgs;
180+
};
181+
182+
auto read_versions = [](const String &pkg)
183+
{
184+
auto &pdb = getPackagesDatabase();
185+
auto versions = pdb.getVersionsForPackage(pkg);
186+
std::vector<String> spkgs;
187+
spkgs.reserve(versions.size());
188+
bool has_versions = false;
189+
for (auto &v : versions)
190+
{
191+
spkgs.push_back(pkg + "-" + v.toString());
192+
if (v.isVersion())
193+
{
194+
has_versions = true;
195+
v.patch = -1;
196+
spkgs.push_back(pkg + "-" + v.toAnyVersion());
197+
v.minor = -1;
198+
spkgs.push_back(pkg + "-" + v.toAnyVersion());
199+
}
200+
}
201+
if (has_versions)
202+
spkgs.push_back(pkg); // self, * version
203+
return spkgs;
204+
};
205+
206+
if (!state)
207+
{
208+
i = -1;
209+
t = old_string ? old_s : text;
210+
spkgs = read_packages(t);
211+
if (spkgs.size() == 1)
212+
spkgs = read_versions(spkgs[0]);
213+
}
214+
215+
while (++i < spkgs.size())
216+
{
217+
if (spkgs[i].find(t) != -1)
218+
{
219+
return strdup(spkgs[i].c_str());
220+
}
221+
}
222+
223+
return nullptr;
224+
}

src/client/main.cpp

Lines changed: 12 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
#include <iostream>
18-
#include <thread>
19-
#include <string>
20-
21-
#include <boost/algorithm/string.hpp>
22-
//#include <readline/readline.h>
17+
#include "build.h"
18+
#include "fix_imports.h"
19+
#include "options.h"
20+
#include "autotools.h"
2321

2422
#include <access_table.h>
2523
#include <api.h>
@@ -36,10 +34,10 @@
3634
#include <shell_link.h>
3735
#include <verifier.h>
3836

39-
#include "build.h"
40-
#include "fix_imports.h"
41-
#include "options.h"
42-
#include "autotools.h"
37+
#include <boost/algorithm/string.hpp>
38+
39+
#include <iostream>
40+
#include <thread>
4341

4442
enum class ApiResult
4543
{
@@ -241,6 +239,10 @@ try
241239

242240
if (cmd == "init")
243241
{
242+
// this prevents db updating (but not initial dl) during dependency helper
243+
Settings::get_system_settings().can_update_packages_db = false;
244+
getPackagesDatabase();
245+
244246
command_init(Strings(args.begin()+2,args.end()));
245247
return 0;
246248
}
@@ -921,94 +923,3 @@ ApiResult api_call(const String &cmd, const Strings &args)
921923

922924
return ApiResult::NotHandled;
923925
}
924-
925-
void command_init(const Strings &args)
926-
{
927-
String project_type = "e";
928-
Project p;
929-
p.name = fs::current_path().filename().string();
930-
931-
auto readline = [](String &d)
932-
{
933-
String s;
934-
std::getline(std::cin, s);
935-
if (!s.empty())
936-
d = s;
937-
};
938-
939-
// interactive mode
940-
if (args.empty())
941-
{
942-
std::cout << "Enter project name [" << p.name << "]: ";
943-
readline(p.name);
944-
std::cout << "Enter project type (e - executable, l - library) [" << project_type << "]: ";
945-
readline(project_type);
946-
std::cout << "Add some dependencies (y/n) [n]: ";
947-
String add_deps;
948-
readline(add_deps);
949-
if (add_deps[0] == 'y')
950-
{
951-
std::cout << "Start entering dependencies' names. You could use TAB to list matching packages.";
952-
}
953-
}
954-
else
955-
{
956-
957-
}
958-
959-
if (project_type[0] == 'l')
960-
p.type = ProjectType::Library;
961-
962-
boost::system::error_code ec;
963-
auto root = fs::current_path();
964-
965-
// checks first
966-
if (fs::exists(root / p.name) ||
967-
fs::exists(root / p.name / "src") ||
968-
fs::exists(root / p.name / "include") ||
969-
fs::exists(root / p.name / "include" / p.name) ||
970-
fs::exists(root / p.name / "include" / p.name / (p.name + ".h")) ||
971-
fs::exists(root / p.name / "src" / (p.name + ".cpp")) ||
972-
0)
973-
throw std::runtime_error("One of the fs objects to be created already exist");
974-
975-
// create, no checks
976-
fs::create_directories(root / p.name / "src");
977-
if (p.type == ProjectType::Library)
978-
{
979-
fs::create_directories(root / p.name / "include" / p.name);
980-
write_file(root / p.name / "src" / (p.name + ".cpp"), "#include <" + p.name + "/" + p.name + ".h>\n\n");
981-
write_file(root / p.name / "include" / p.name / (p.name + ".h"), "//#include <something>\n\n");
982-
}
983-
else
984-
{
985-
write_file(root / p.name / "src" / (p.name + ".cpp"), "//#include <something>\n\n"
986-
"int main(int argc, char **argv)\n{\n return 0;\n}\n");
987-
}
988-
989-
p.root_directory = p.name;
990-
991-
yaml y;
992-
if (!fs::exists(CPPAN_FILENAME))
993-
{
994-
y = p.save();
995-
}
996-
else
997-
{
998-
auto orig = load_yaml_config(path(CPPAN_FILENAME));
999-
Config c;
1000-
c.allow_relative_project_names = true;
1001-
//c.allow_local_dependencies = true;
1002-
c.load(orig);
1003-
auto &projects = c.getProjects();
1004-
if (projects.find(p.name) != projects.end())
1005-
throw std::runtime_error("Project " + p.name + " already exists in the config");
1006-
projects[p.name] = p;
1007-
y = c.save();
1008-
orig["projects"] = y["projects"];
1009-
y = orig;
1010-
}
1011-
dump_yaml_config(CPPAN_FILENAME, y);
1012-
1013-
build(root);
1014-
}

0 commit comments

Comments
 (0)