Advertisement
Guest User

Untitled

a guest
Dec 15th, 2018
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.86 KB | None | 0 0
  1. /**
  2. * CPSC 362 VCS Project
  3. * Copyright(C) 2018 Team TBD
  4. * @author Josh Gomberg jgomberg93@gmail.com
  5. * @author Michael Li limichael1099419@gmail.com
  6. * @author Frank Ngo frank.ngo@csu.fullerton.edu
  7. * @author Wellson Pan dihydrogenmonoxide1337@gmail.com
  8. *
  9. * Header.h contains the libraries and functions used in main.cpp
  10. **/
  11.  
  12. #pragma warning(disable : 4996)
  13. #include <iostream>
  14. #include <string>
  15. #include <fstream>
  16. #include <vector>
  17. #include <cmath>
  18. #include <ctime>
  19. #include <chrono>
  20. #include <ratio>
  21. #include <boost/filesystem.hpp>
  22. #include <boost/range.hpp>
  23. namespace fs = boost::filesystem;
  24.  
  25. /***Remove Substrs
  26. parameter - variable to remove from, variable to remove
  27. -passes by reference the first variable
  28. */
  29. void removeSubstrs(std::string& destination, std::string source) {
  30. std::string::size_type n = source.length();
  31. for (std::string::size_type i = destination.find(source);
  32. i != std::string::npos;
  33. i = destination.find(source))
  34. destination.erase(i, n);
  35. }
  36.  
  37. /**
  38. * Show the menu prompt and ask for user's input
  39. *
  40. * @return int user's input
  41. **/
  42. int prompt()
  43. {
  44. int input;
  45. std::cout << "What would you like to do?" << std::endl;
  46. std::cout << "1. Create repo" << std::endl;
  47. std::cout << "2. Push to repo" << std::endl;
  48. std::cout << "3. Pull from repo" << std::endl;
  49. std::cout << "4. Label manifest" << std::endl;
  50. std::cout << "5. Merge" << std::endl;
  51. std::cout << "6. Exit" << std::endl;
  52. std::cout << "Enter the number corresponding with the command: ";
  53. std::cin >> input;
  54. std::cin.ignore(256, '\n');
  55. return input;
  56. }
  57.  
  58. /**
  59. * Find the total number of files within a folder and its sub-folders.
  60. *
  61. * @param string p path to the folder
  62. * @return int the size of that folder
  63. **/
  64. int directorySize(std::string p)
  65. {
  66. int i = 0;
  67. for (fs::recursive_directory_iterator it(p); it != fs::recursive_directory_iterator(); ++it)
  68. {
  69. i++;
  70. }
  71. return i;
  72. }
  73.  
  74. /**
  75. * Calculate the weighted checksum.
  76. *
  77. * @param char c the character to get the checksum from based on its ASCII value
  78. * @param int counter the index of char c within a file
  79. * @return int the weighted checksum
  80. **/
  81. int checksum(char c, int counter)
  82. {
  83. int checkSum = 0;
  84. switch (counter % 5)
  85. {
  86. case 0:
  87. checkSum += (c * 1);
  88. break;
  89. case 1:
  90. checkSum += (c * 3);
  91. break;
  92. case 2:
  93. checkSum += (c * 7);
  94. break;
  95. case 3:
  96. checkSum += (c * 11);
  97. break;
  98. case 4:
  99. checkSum += (c * 17);
  100. break;
  101. }
  102. //prevent overflowing in case the checksum gets too large
  103. int m = (std::pow(2, 31)) - 1;
  104. checkSum = checkSum % m;
  105. return checkSum;
  106. }
  107.  
  108. /*
  109. * Get the current time from system's clock
  110. *
  111. * @return string the current time
  112. **/
  113. std::string getCurrentTime()
  114. {
  115. std::chrono::duration<int, std::ratio<60 * 60 * 24> > one_day(1);
  116. std::chrono::system_clock::time_point today = std::chrono::system_clock::now();
  117. time_t tt;
  118. tt = std::chrono::system_clock::to_time_t(today);
  119. std::string currentTime = ctime(&tt);
  120. std::string currentTimeFixed = "";
  121. for (int i = 0; i < currentTime.length() - 1; i++)
  122. {
  123. if (currentTime[i] == ' ')
  124. {
  125. currentTimeFixed += "_";
  126. }
  127. else if (currentTime[i] == ':')
  128. {
  129. currentTimeFixed += "-";
  130. }
  131. else
  132. {
  133. currentTimeFixed += currentTime[i];
  134. }
  135. }
  136.  
  137. return currentTimeFixed;
  138. }
  139.  
  140. /**
  141. * Compares the file contents to see what has changed
  142. *
  143. * @param string destination path to destination folder
  144. * @param string source path to source folder
  145. *
  146. * @return vector<string> changed elements
  147. **/
  148. std::vector<std::string> compareFiles(std::vector<std::string> destination, std::string source)
  149. {
  150. std::ifstream latest_manifest(source);
  151. std::string line;
  152. std::vector<std::string> changed, changed1, dest(destination);
  153. std::string time = getCurrentTime();
  154. std::vector<bool> isNew(destination.size(), true);
  155.  
  156. do
  157. {
  158. std::getline(latest_manifest, line);
  159. if (!line.empty())
  160. {
  161. changed1.push_back(line);
  162. std::size_t pos = line.find("\t");
  163. std::string filename = line.substr(0, pos);
  164. changed.push_back(filename);
  165. }
  166. } while (latest_manifest.good());
  167.  
  168. for (std::size_t a = 0; a < dest.size(); a++)
  169. {
  170. for (std::size_t b = 0; b < changed.size(); b++)
  171. {
  172. std::size_t pos = dest[a].find("\t");
  173. std::string filename = dest[a].substr(0, pos);
  174.  
  175. if (filename == changed[b])
  176. {
  177. changed.erase(changed.begin() + b);
  178. isNew[a] = false;
  179. }
  180. }
  181. }
  182. for (int a = 0; a < changed.size(); a++)
  183. {
  184. for (int b = 0; b < changed1.size(); b++)
  185. {
  186. std::size_t pos = changed1[b].find("\t");
  187. std::string filename = changed1[b].substr(0, pos);
  188.  
  189. if (filename == changed[a])
  190. {
  191. changed1[b] = changed[a] + "\t" + time;
  192. }
  193. }
  194. }
  195.  
  196. for (std::size_t a = 0; a < destination.size(); a++)
  197. {
  198. if (isNew[a])
  199. {
  200. changed1.push_back(destination[a] + "\t" + time);
  201. }
  202. }
  203.  
  204. return changed1;
  205. }
  206.  
  207.  
  208. /**
  209. * Compares the file names to see what has changed
  210. *
  211. * @param string destination_f filename in destination folder
  212. * @param string source_f filename in source folder
  213. *
  214. * @return vector<string> changed elements
  215. **/
  216. std::vector<std::string> compareFiles(std::string destination_f, std::string source_f)
  217. {
  218. std::ifstream source(source_f);
  219. std::ifstream destination(destination_f);
  220. std::string line;
  221.  
  222. std::vector<std::string> src, dest;
  223.  
  224. do {
  225. std::getline(source, line);
  226. std::size_t pos = line.find("\t");
  227. std::string filename = line.substr(0, pos);
  228. src.push_back(filename);
  229. } while (source.good());
  230.  
  231. do {
  232. std::getline(destination, line);
  233. std::size_t pos = line.find("\t");
  234. std::string filename = line.substr(0, pos);
  235. dest.push_back(filename);
  236. } while (destination.good());
  237.  
  238. for (std::size_t a = 0; a < src.size(); a++)
  239. {
  240. for (std::size_t b = 0; b < dest.size(); b++)
  241. {
  242. if (dest[b] == src[a])
  243. {
  244. src.erase(src.begin() + a);
  245. }
  246. }
  247. }
  248.  
  249. return src;
  250. }
  251.  
  252. /**
  253. * Get the path to the most recent manifest
  254. *
  255. * @param path man_dir path to the manifest folder
  256. *
  257. * @return path path to the most recent manifest
  258. **/
  259. fs::path MostRecentManifest(fs::path man_dir)
  260. {
  261. fs::path latest_manifest;
  262. std::time_t latest_tm{};
  263.  
  264. for (auto&& entry : boost::make_iterator_range(fs::directory_iterator(man_dir), {}))
  265. {
  266. fs::path p = entry.path();
  267. if (is_regular_file(p) && p.extension() == ".txt")
  268. {
  269. std::time_t timestamp = fs::last_write_time(p);
  270. if (timestamp > latest_tm)
  271. {
  272. latest_manifest = p;
  273. latest_tm = timestamp;
  274. }
  275. }
  276. }
  277.  
  278. return latest_manifest;
  279. }
  280.  
  281. /**
  282. * Create the manifest file
  283. *
  284. * @param path source path to the source folder
  285. **/
  286. void createManifest(fs::path source)
  287. {
  288. std::string manifest_path = source.string() + "\\Manifest\\";
  289. std::string currentTime = getCurrentTime();
  290. std::string t = manifest_path + currentTime + ".txt";
  291.  
  292. std::vector<fs::directory_entry> container(directorySize(source.string()));
  293. copy(fs::recursive_directory_iterator(source), fs::recursive_directory_iterator(), container.begin());
  294.  
  295. //CREATING MANIFEST DIRECTORY
  296. if (fs::create_directory(manifest_path))
  297. {
  298.  
  299. //CREATING MANIFEST FILE
  300. std::ofstream manifest(t);
  301. if (manifest.fail())
  302. std::cerr << "Couldn't open the file\n";
  303.  
  304. for (int i = 0; i < container.size(); i++)
  305. {
  306. std::string s = container[i].path().string();
  307. removeSubstrs(s, source.parent_path().string());
  308. manifest << s << "\t" << currentTime << std::endl;
  309. }
  310. manifest.close();
  311. }
  312.  
  313. else
  314. {
  315. //std::cerr << "Manifest already exists\n";
  316.  
  317. fs::path man(manifest_path);
  318. fs::path recent(MostRecentManifest(man));
  319. std::vector<std::string> vec;
  320.  
  321.  
  322.  
  323. for (int i = 0; i < container.size(); i++)
  324. {
  325. std::string s = container[i].path().string();
  326. removeSubstrs(s, source.parent_path().string());
  327. vec.push_back(s);
  328. }
  329.  
  330. vec = compareFiles(vec, recent.string());
  331.  
  332. std::ofstream manifest(t);
  333.  
  334. for (int i = 0; i < vec.size(); i++)
  335. {
  336. manifest << vec[i] << std::endl;
  337. }
  338.  
  339. manifest.close();
  340. }
  341. }
  342.  
  343. /**
  344. * Push to the Repository
  345. Parameters : source directory and the Repository
  346. -Incomplete
  347. bug: it makes duplicate files.
  348. **/
  349. void pushToRepo(std::string repo, std::string dir)
  350. {
  351. fs::path from{ dir };
  352. fs::path to{ repo };
  353.  
  354. std::vector<fs::directory_entry> container(directorySize(dir));
  355.  
  356. copy(fs::recursive_directory_iterator(from), fs::recursive_directory_iterator(), container.begin());
  357.  
  358. for (int i = 0; i < container.size(); i++)
  359. {
  360. //if the path points to a file
  361. //checksum the file to get ArtifactID
  362. if (fs::is_regular_file(container[i].path()))
  363. {
  364. size_t found = container[i].path().string().find("\\Manifest\\");
  365. if (found != std::string::npos)
  366. {
  367. std::cerr << "Don't need to copy Manifest files\n";
  368. }
  369. else
  370. {
  371. //go through directory path to file and get its checksum
  372. std::ifstream infile(container[i].path().string());
  373. char c;
  374. int checkSum = 0;
  375. int counter = 0;
  376. while (infile.get(c))
  377. {
  378. checkSum += checksum(c, counter);
  379. counter++;
  380. }
  381. infile.close();
  382.  
  383. std::string s = container[i].path().string();
  384.  
  385. removeSubstrs(s, from.parent_path().string());
  386.  
  387. std::ifstream newInFile(container[i].path().string());
  388.  
  389. std::string outputFile = repo + "\\" + s + "\\";
  390.  
  391. fs::path temp{ outputFile.c_str() };
  392. fs::create_directories(outputFile);
  393.  
  394. outputFile = outputFile + std::to_string(checkSum) + "-L" + std::to_string(counter) + container[i].path().extension().string();
  395.  
  396. std::ofstream outFile(outputFile);
  397. std::string d;
  398. while (std::getline(newInFile, d))
  399. {
  400. outFile << d;
  401. outFile << "\n";
  402. }
  403. newInFile.close();
  404. outFile.close();
  405. }
  406. }
  407.  
  408. createManifest(repo);
  409. }
  410. }
  411.  
  412. /*** Reads Manifest file/path
  413. -parameter - manifest
  414. -output - vector of manifest contents */
  415. std::vector<std::string> ReadManifest(std::string manifest)
  416. {
  417. std::ifstream man_file;
  418. man_file.open(manifest);
  419.  
  420. std::string line;
  421. std::vector<std::string> stuff;
  422.  
  423. do
  424. {
  425. std::getline(man_file, line);
  426. if (!line.empty())
  427. {
  428. std::size_t pos = line.find("\t");
  429. std::string filename = line.substr(0, pos);
  430. stuff.push_back(filename);
  431. }
  432. } while (man_file.good());
  433.  
  434. return stuff;
  435. }
  436.  
  437. /**
  438. * Pull from a repository
  439. Parameters: your own source directory and the Repository
  440. -Incomplete : Have yet to find a way to an efficient way to compare the directories.
  441. -because the paths are full paths and we need to reduce them into related paths.
  442. */
  443. void pullFromRepo(std::string dir, std::string repo)
  444. {
  445. std::string line, label, manName;
  446. std::size_t pos;
  447. int labeled = 0;
  448.  
  449. std::ifstream labelFileIn("labels.txt");
  450.  
  451. std::cout << "What is the label or manifest name you would like to pull? ";
  452. std::cin >> label;
  453.  
  454. while (labelFileIn.good())
  455. {
  456. std::getline(labelFileIn, line);
  457. pos = line.find(label);
  458. if (pos != std::string::npos) {
  459. labeled = 1;
  460. break;
  461. }
  462. }
  463.  
  464. if (labeled == 1) {
  465. pos = line.find("\t");
  466. manName = line.substr(0, pos);
  467. }
  468.  
  469. else
  470. manName = label;
  471.  
  472. std::string manifest_file = repo + "\\Manifest\\" + manName + ".txt";
  473.  
  474. std::vector<std::string> files = ReadManifest(manifest_file);
  475.  
  476. fs::path dest(repo);
  477.  
  478. for (size_t i = 0; i < files.size(); i++)
  479. {
  480. fs::path one(files[i]);
  481. fs::path sauce = dest.parent_path().string() + one.string();
  482.  
  483. if (fs::is_regular_file(sauce))
  484. {
  485. size_t found = sauce.string().find("\\Manifest\\");
  486. if (found != std::string::npos)
  487. {
  488. std::cerr << "Don't need to copy Manifest files\n";
  489. }
  490.  
  491. else
  492. {
  493.  
  494. files[i] = one.parent_path().string();
  495.  
  496. fs::path destinado = dir + files[i];
  497.  
  498. fs::create_directories(destinado.parent_path().string());
  499.  
  500. std::ifstream newInFile(sauce.string());
  501. std::ofstream outFile(destinado.string());
  502.  
  503. std::string d;
  504. while (std::getline(newInFile, d))
  505. {
  506. outFile << d;
  507. outFile << "\n";
  508. }
  509.  
  510. newInFile.close();
  511. outFile.close();
  512. }
  513. }
  514. }
  515.  
  516. createManifest(repo);
  517. }
  518. /**
  519. * Create label for the manifest file
  520. **/
  521. void labelManifest()
  522. {
  523. std::string manName, label;
  524.  
  525. std::cout << "What is the name of the manifest file? ";
  526. std::cin >> manName;
  527.  
  528. std::cout << "What label would you like to give the manifest file? ";
  529. std::cin >> label;
  530.  
  531. std::ofstream labelFile("labels.txt", std::ios_base::app);
  532.  
  533. labelFile << manName << "\t" << label << " \n";
  534. }
  535.  
  536. /*
  537. Compare
  538. -Compares string vectors to see the difference or similarity
  539. -parameter : two string vectors and a mode to determine which vector to return.
  540. */
  541. std::vector<std::string> compare(std::vector<std::string> one, std::vector<std::string> two, int comp)
  542. {
  543. std::vector<std::string> same;
  544. std::vector<std::string> different;
  545.  
  546. for (size_t i = 0; i < one.size(); i++)
  547. {
  548. for (size_t j = 0; j < two.size(); j++)
  549. {
  550. if (one[i] == two[j])
  551. {
  552. two.erase(two.begin() + j);
  553. one.erase(one.begin() + i);
  554. same.push_back(one[i]);
  555. }
  556. }
  557. }
  558.  
  559.  
  560. for (size_t i = 0; i < one.size(); i++)
  561. {
  562. different.push_back(one[i]);
  563. }
  564. for (size_t i = 0; i < two.size(); i++)
  565. {
  566. different.push_back(two[i]);
  567. }
  568.  
  569.  
  570.  
  571. if (comp == 1)
  572. return one; //1st set - 2nd set
  573. else if (comp == 2)
  574. return two; //2nd set - 1st set
  575. else if (comp == 3)
  576. return same; //same set
  577. else if (comp == 4)
  578. return different;
  579. else
  580. return one;
  581. }
  582.  
  583. /*
  584. Merge
  585. -combines desired manifest contents in the repo with the source directory
  586. -parameter = source direectory and repository
  587. */
  588. void Merge(std::string dir, std::string repo)
  589. {
  590.  
  591. std::string line, label, manName;
  592. std::size_t pos;
  593. int labeled = 0;
  594.  
  595. std::ifstream labelFileIn("labels.txt");
  596.  
  597. std::cout << "What is the label or manifest name you would like to merge? ";
  598. std::cin >> label;
  599.  
  600. while (labelFileIn.good())
  601. {
  602. std::getline(labelFileIn, line);
  603. pos = line.find(label);
  604. if (pos != std::string::npos) {
  605. labeled = 1;
  606. break;
  607. }
  608. }
  609.  
  610. if (labeled == 1) {
  611. std::size_t pos = line.find("\t");
  612. manName = line.substr(0, pos);
  613. }
  614.  
  615. else
  616. manName = label;
  617.  
  618. fs::path sour(dir);
  619. createManifest(sour);
  620.  
  621. fs::path man_path(dir + "\\Manifest\\");
  622.  
  623. fs::path s = MostRecentManifest(man_path);
  624.  
  625. std::vector<std::string> src_man = ReadManifest(s.string());
  626.  
  627. std::string manifest_file = repo + "\\Manifest\\" + manName + ".txt";
  628.  
  629. std::vector<std::string> files = ReadManifest(manifest_file);
  630.  
  631. std::vector<std::string> same = compare(files, src_man, 3);
  632.  
  633. std::vector<std::string> diff = compare(files, src_man, 2);
  634.  
  635. fs::path dest(repo);
  636.  
  637. for (size_t i = 0; i < diff.size(); i++)
  638. {
  639.  
  640. fs::path one(diff[i]);
  641. fs::path sauce = dest.parent_path().string() + one.string();
  642.  
  643. if (fs::is_regular_file(sauce))
  644. {
  645. size_t found = sauce.string().find("\\Manifest\\");
  646. if (found != std::string::npos)
  647. {
  648.  
  649. }
  650.  
  651. else
  652. {
  653.  
  654. diff[i] = one.parent_path().string();
  655.  
  656. fs::path destinado = dir + diff[i];
  657.  
  658. std::string tempFilename = "", tempFilename2 = "", tempFilename3 = "";
  659.  
  660. for (int i = sauce.string().length() - 1; i > 0; i--)
  661. {
  662. if (sauce.string()[i] != '\\')
  663. {
  664. tempFilename += sauce.string()[i];
  665. }
  666. else
  667. {
  668. for (int j = 0; j < i; j++)
  669. {
  670. tempFilename3 += sauce.string()[j];
  671. }
  672. break;
  673. }
  674. }
  675.  
  676. for (int i = tempFilename.length() - 1; i >= 0; i--)
  677. {
  678. tempFilename2 += tempFilename[i];
  679. }
  680.  
  681. std::ifstream newInFile(sauce.string());
  682. std::ofstream outFile(dir + '\\' + "MR_" + tempFilename2);
  683. std::ofstream outFile2(dir + '\\' + "MG_" + tempFilename2);
  684.  
  685. std::string d;
  686. while (std::getline(newInFile, d))
  687. {
  688. outFile << d;
  689. outFile << "\n";
  690. outFile2 << d;
  691. outFile2 << "\n";
  692. }
  693.  
  694. newInFile.close();
  695. outFile.close();
  696.  
  697. fs::path anotherInFile(dir + '\\' + "MT_" + tempFilename2);
  698. fs::rename(sauce, anotherInFile);
  699. }
  700. }
  701. }
  702.  
  703. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement