Skip to content

Commit 2346f6c

Browse files
committed
Add tools
1 parent 656d7f0 commit 2346f6c

File tree

4 files changed

+221
-0
lines changed

4 files changed

+221
-0
lines changed

tools/create-index.mjs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import { execSync } from 'child_process';
4+
import yaml from 'js-yaml';
5+
6+
const getGitHubUrl = (rootPath) => {
7+
try {
8+
// Get the GitHub repository URL
9+
const remoteUrl = execSync('git config --get remote.origin.url', { cwd: rootPath, encoding: 'utf-8' }).trim();
10+
11+
// Convert SSH format to HTTPS format
12+
const httpsUrl = remoteUrl.replace(/^git@github\.com:/, 'https://github.com/').replace(/\.git$/, '');
13+
14+
return httpsUrl;
15+
} catch (error) {
16+
console.error(`Error getting GitHub repository URL: ${error.message}`);
17+
return null;
18+
}
19+
};
20+
21+
const getCurrentBranch = (rootPath) => {
22+
try {
23+
// Get the current branch name
24+
const branchName = execSync('git branch --show-current', { cwd: rootPath, encoding: 'utf-8' }).trim();
25+
return branchName;
26+
} catch (error) {
27+
console.error(`Error getting current branch: ${error.message}`);
28+
return null;
29+
}
30+
};
31+
32+
const getRepositoryRoot = (rootPath) => {
33+
try {
34+
// Get the root folder of the repository
35+
const repositoryRoot = execSync('git rev-parse --show-toplevel', { cwd: rootPath, encoding: 'utf-8' }).trim();
36+
return repositoryRoot;
37+
} catch (error) {
38+
console.error(`Error getting repository root: ${error.message}`);
39+
return null;
40+
}
41+
};
42+
43+
const searchPackages = (directory, outputFilename, indexUrl) => {
44+
const result = { packages: [] };
45+
46+
const repositoryRoot = getRepositoryRoot(directory);
47+
const gitHubUrl = getGitHubUrl(repositoryRoot);
48+
const currentBranch = getCurrentBranch(repositoryRoot);
49+
50+
if (!repositoryRoot || !gitHubUrl || !currentBranch) {
51+
return;
52+
}
53+
54+
const search = (dir, rootPath) => {
55+
const files = fs.readdirSync(dir);
56+
57+
for (const file of files) {
58+
const filePath = path.join(dir, file);
59+
const isDirectory = fs.statSync(filePath).isDirectory();
60+
61+
if (isDirectory) {
62+
search(filePath, rootPath);
63+
} else {
64+
const isPackageJson = file === 'package.json';
65+
const isManifestPy = file === 'manifest.py';
66+
67+
if (isPackageJson || isManifestPy) {
68+
const packageInfo = {
69+
name: path.basename(dir),
70+
docs: constructGitHubUrl(gitHubUrl, currentBranch, repositoryRoot, dir),
71+
index: indexUrl,
72+
};
73+
74+
if (isManifestPy) {
75+
try {
76+
const content = fs.readFileSync(filePath, 'utf8');
77+
const descriptionMatch = /description="(.*?)"/.exec(content);
78+
79+
if (descriptionMatch && descriptionMatch[1]) {
80+
packageInfo.description = descriptionMatch[1];
81+
}
82+
} catch (error) {
83+
console.error(`Error reading ${file}: ${error.message}`);
84+
}
85+
}
86+
87+
result.packages.push(packageInfo);
88+
}
89+
}
90+
}
91+
};
92+
93+
const constructGitHubUrl = (baseUrl, branch, repositoryRoot, dirPath) => {
94+
const relativePath = path.relative(repositoryRoot, dirPath);
95+
const normalizedPath = relativePath.replace(/\\/g, '/'); // Normalize path separators for Windows
96+
97+
return `${baseUrl}/tree/${branch}/${normalizedPath}`;
98+
};
99+
100+
search(directory, repositoryRoot);
101+
102+
try {
103+
const yamlData = yaml.dump(result);
104+
fs.writeFileSync(outputFilename, `---\n${yamlData}`);
105+
console.log(`YAML file saved to ${outputFilename}`);
106+
} catch (error) {
107+
console.error(`Error writing YAML file: ${error.message}`);
108+
}
109+
};
110+
111+
// Check if command line arguments are provided
112+
if (process.argv.length < 5) {
113+
// Note: Official MicroPython lib index is: https://micropython.org/pi/v2
114+
// Example usage: node create-index.mjs ../micropython-lib/micropython micropython-lib.yml https://micropython.org/pi/v2
115+
console.error('Usage: node create-index.mjs <directory> <outputFilename.yml> <indexUrl>');
116+
} else {
117+
const directory = process.argv[2];
118+
const outputFilename = process.argv[3];
119+
const indexUrl = process.argv[4];
120+
121+
searchPackages(directory, outputFilename, indexUrl);
122+
}

tools/find-broken-packages.mjs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// This script helps to find packages in the Arduino package index that are missing the package.json file.
2+
// Without the package.json file, the package cannot be installed using mpremote or the Arduino Package Installer.
3+
4+
import yaml from 'js-yaml';
5+
6+
function convertToRawURL(url, suffix = null) {
7+
url = url.replace('https://github.com/', '');
8+
const parts = url.split('/');
9+
const owner = parts[0];
10+
const repoName = parts[1];
11+
const branch = 'HEAD';
12+
let path = parts[2] ? "/" + parts[2] : '';
13+
if (suffix) {
14+
path += "/" + suffix;
15+
}
16+
return `https://raw.githubusercontent.com/${owner}/${repoName}/${branch}${path}`;
17+
}
18+
19+
const indexURL = "https://raw.githubusercontent.com/arduino/package-index-py/refs/heads/main/package-list.yaml";
20+
const data = await fetch(indexURL);
21+
const doc = yaml.load(await data.text());
22+
23+
// Filter packages that have the package_descriptor field
24+
// which overrides the package.json file
25+
doc.packages = doc.packages.filter(pkg => pkg.package_descriptor == undefined);
26+
doc.packages.map(pkg => {
27+
// Convert the URLs to https://raw.githubusercontent.com/... format
28+
pkg.rawURL = convertToRawURL(pkg.url, 'package.json');
29+
return pkg;
30+
});
31+
32+
let incompletePackages = [];
33+
34+
// Check the existence of the package.json file for each package
35+
for (const aPackage of doc.packages) {
36+
const response = await fetch(aPackage.rawURL);
37+
if (!response.ok) {
38+
incompletePackages.push(aPackage.url);
39+
console.log(`❌ Package file ${aPackage.rawURL} not found.`);
40+
} else {
41+
console.log(`✅ Package file ${aPackage.rawURL} found.`);
42+
}
43+
}
44+
45+
console.log("\n👀 Packages with missing package.json:");
46+
console.log(incompletePackages);
47+
const message = `
48+
Consider making pull requests to add a package.json file to these repositories
49+
or add the package_descriptor field to the package in the package-list.yaml file
50+
`;
51+
console.log(message);

tools/package-lock.json

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "tools",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"scripts": {
6+
"test": "echo \"Error: no test specified\" && exit 1"
7+
},
8+
"author": "",
9+
"license": "ISC",
10+
"description": "",
11+
"dependencies": {
12+
"js-yaml": "^4.1.0"
13+
}
14+
}

0 commit comments

Comments
 (0)