Skip to content

Commit

Permalink
#210 Added scanning support for linux (testing needed)
Browse files Browse the repository at this point in the history
  • Loading branch information
czprz committed Apr 6, 2023
1 parent 0ed9db1 commit f49fe90
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 80 deletions.
2 changes: 1 addition & 1 deletion bin/execution/default-yargs-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import init from "../init.js";

import path from 'path';
import chalk from 'chalk';
import scanner from "../scanner.js";
import scanner from "../scanner/index.js";

"use strict";
export default new class {
Expand Down
91 changes: 12 additions & 79 deletions bin/scanner.js → bin/scanner/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import chalk from "chalk";
import readline from "readline";
import path from "path";
import fs from "fs";
import {execSync} from "child_process";
import os from "os";

import projectConfigFacade from "./configuration/facades/project-config-facade.js";
import projectConfigFacade from "../configuration/facades/project-config-facade.js";

import winScan from './windows.js';
import linScan from './linux.js';

"use strict";
export default new class {
Expand Down Expand Up @@ -36,12 +38,14 @@ export default new class {
async #findProjects() {
console.log('Scanning has started.. Please wait..');

const paths = [];
const disks = this.#getDisks();
let paths = [];

for (const disk of disks) {
const files = this.#findFilesByName(disk, 'dever.json');
paths.push(...files);
if (os.platform() === 'win32') {
paths = await winScan.scan();
} else if (os.platform() === 'linux') {
paths = await linScan.scan();
} else {
throw new Error('Unsupported operating system: ' + os.platform());
}

if (paths?.length === 0) {
Expand Down Expand Up @@ -102,75 +106,4 @@ export default new class {
console.warn(chalk.yellow(`Check 'dever list --not-supported' to get a list of the unsupported projects`));
}
}

/**
* Check if the folder should be skipped
* @param folderName {string}
* @returns {boolean}
*/
#isSkipFolder(folderName) {
return ['Windows', 'Program Files', 'Program Files (x86)', 'ProgramData', 'AppData', 'node_modules'].includes(folderName);
}

/**
* Find all files with the given name
* @param rootPath {string}
* @param filename {string}
* @param files {string[]}
* @returns {string[]}
*/
#findFilesByName(rootPath, filename, files = []) {
try {
if (fs.existsSync(rootPath)) {
const contents = fs.readdirSync(rootPath);

for (const file of contents) {
const filePath = path.join(rootPath, file);

try {
const fileStat = fs.statSync(filePath);

if (fileStat.isDirectory()) {
if (!this.#isSkipFolder(file)) {
this.#findFilesByName(filePath, filename, files);
}
} else if (file === filename) {
files.push(filePath);
}
} catch (err) {
if (err.code !== 'EPERM' && err.code !== 'EBUSY' && err.code !== 'EACCES' && err.code !== 'ENOENT') {
throw err;
}
}
}
}
} catch (err) {
if (err.code !== 'EPERM' && err.code !== 'EACCES' && err.code !== 'ENOENT') {
throw err;
}
}

return files;
}

/**
* Get all local disks volume names
* @returns {Array<string>}
*/
#getDisks() {
const disks = [];

const output = execSync('wmic logicaldisk get deviceid, volumename, description, mediatype').toString();
const lines = output.trim().split('\r\n').slice(1);

for (const line of lines) {
const [_, volumeName, mediaType] = line.trim().split(/\s{2,}/);

if (mediaType === '12') {
disks.push(volumeName + '\\');
}
}

return disks;
};
}
74 changes: 74 additions & 0 deletions bin/scanner/linux.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import fs from "fs";
import path from "path";

export default new class {
#searchDirs = ['/home', '/opt', '/var', '/usr/local'];

/**
* Gets all dever.json paths on linux
* @returns {Promise<string[]>} paths
*/
async scan() {
// TODO: Needs testing
const paths = [];

for (const dir of this.#searchDirs) {
const foundPaths = this.#findReposAndJsonFiles(dir);
paths.push(...foundPaths);
}

return paths;
}

/**
* Finds folder to scan
* @param dir {string}
* @returns {string[]}
*/
#findReposAndJsonFiles(dir) {
const items = fs.readdirSync(dir);

// TODO: Does it have to be a git repository folder?
if (items.includes('.git')) {
const gitDir = path.join(dir, '.git');
return this.#searchForJsonFiles(gitDir);
}

const paths = [];

for (const item of items) {
const itemPath = path.join(dir, item);
if (fs.statSync(itemPath).isDirectory()) {
if (item === 'node_modules' || item === '.git' || item === '.svn' || item === '.hg' || item === 'bower_components') {
continue;
}

const foundPaths = this.#findReposAndJsonFiles(itemPath);
paths.push(...foundPaths);
}
}

return paths;
}

/**
* Searches for dever.json files
* @param dir {string}
* @returns {string[]}
*/
#searchForJsonFiles(dir) {
const jsonFiles = [];
const items = fs.readdirSync(dir);

for (const item of items) {
const itemPath = path.join(dir, item);
const stats = fs.statSync(itemPath);

if (stats.isFile() && path.extname(item) === 'dever.json') {
jsonFiles.push(itemPath);
}
}

return jsonFiles;
}
}
92 changes: 92 additions & 0 deletions bin/scanner/windows.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import fs from "fs";
import path from "path";
import {execSync} from "child_process";

export default new class {
/**
* Gets all dever.json paths on windows
* @returns {Promise<string[]>} paths
*/
async scan() {
const paths = [];
const disks = this.#getDisks();

for (const disk of disks) {
const files = this.#findFilesByName(disk, 'dever.json');
paths.push(...files);
}

return paths;
}

/**
* Check if the folder should be skipped
* @param folderName {string}
* @returns {boolean}
*/
#isSkipFolder(folderName) {
return ['Windows', 'Program Files', 'Program Files (x86)', 'ProgramData', 'AppData', 'node_modules'].includes(folderName);
}

/**
* Find all files with the given name
* @param rootPath {string}
* @param filename {string}
* @param files {string[]}
* @returns {string[]}
*/
#findFilesByName(rootPath, filename, files = []) {
try {
if (fs.existsSync(rootPath)) {
const contents = fs.readdirSync(rootPath);

for (const file of contents) {
const filePath = path.join(rootPath, file);

try {
const fileStat = fs.statSync(filePath);

if (fileStat.isDirectory()) {
if (!this.#isSkipFolder(file)) {
this.#findFilesByName(filePath, filename, files);
}
} else if (file === filename) {
files.push(filePath);
}
} catch (err) {
if (err.code !== 'EPERM' && err.code !== 'EBUSY' && err.code !== 'EACCES' && err.code !== 'ENOENT') {
throw err;
}
}
}
}
} catch (err) {
if (err.code !== 'EPERM' && err.code !== 'EACCES' && err.code !== 'ENOENT') {
throw err;
}
}

return files;
}

/**
* Get all local disks volume names
* @returns {Array<string>}
*/
#getDisks() {
const disks = [];

const output = execSync('wmic logicaldisk get deviceid, volumename, description, mediatype').toString();
const lines = output.trim().split('\r\n').slice(1);

for (const line of lines) {
const [_, volumeName, mediaType] = line.trim().split(/\s{2,}/);

if (mediaType === '12') {
disks.push(volumeName + '\\');
}
}

return disks;
}
}

0 comments on commit f49fe90

Please sign in to comment.