Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/.idea
/.vscode

# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Logs
logs
*.log
Expand Down Expand Up @@ -104,4 +117,5 @@ dist
.tern-port

package-lock.json
script.sh
yarn.lock
script.sh
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ If you change your mind about these commits later, you can delete the repository

## Requested Information 🌳

| Key | Description | Default value |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| Key | Description | Default value |
|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|
| `git` | The type of Git server with which you'd like to sync contributions (github, gitlab) | github |
| `gituri` | Tthe Github/Gitlab server (no trailing slash) with which you'd like to sync contributions | https://github.com |
| `username` | The username whose graph contributions you'd like to copy. | |
| `year` | Year that you would like to sync with provided `username`. Currently doesn't support multiple years. | Current year |
| `execute` | Let's the code know whether to simply generate `script.sh` that, when executed, will force push commits to `main`. Or to both generate and execute at once. | `false`, in other words generate _without_ execution |
| `confirm` | A quick double check that you're ready to proceed. |
| `year` | Year that you would like to sync with provided `username`. Currently doesn't support multiple years. | Current year |
| `execute` | Let's the code know whether to simply generate `script.sh` that, when executed, will force push commits to `main`. Or to both generate and execute at once. | `false`, in other words generate _without_ execution |
| `confirm` | A quick double check that you're ready to proceed. |

## How do I know this is secure? 🔒

Expand Down
63 changes: 34 additions & 29 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,47 @@
import { parse } from "node-html-parser";
import {parse} from "node-html-parser";
import axios from "axios";
import fs from "fs";
import shell from "shelljs";

// Gathers needed git commands for bash to execute per provided contribution data.
const getCommand = (contribution) => {
return `GIT_AUTHOR_DATE=${contribution.date}T12:00:00 GIT_COMMITER_DATE=${contribution.date}T12:00:00 git commit --allow-empty -m "Rewriting History!" > /dev/null\n`.repeat(
contribution.count
);
return `GIT_AUTHOR_DATE=${contribution.date}T12:00:00 GIT_COMMITER_DATE=${contribution.date}T12:00:00 git commit --allow-empty -m "Rewriting History!" > /dev/null\n`.repeat(
contribution.count
);
};

export default async (input) => {
// Returns contribution graph html for a full selected year.
const res = await axios.get(
`https://github.com/users/${input.username}/contributions?tab=overview&from=${input.year}-12-01&to=${input.year}-12-31`
);
// Returns the URL of the Git server.
const api_uri = `https://github.com/users/${input.username}/contributions?tab=overview&from=${input.year}-12-01&to=${input.year}-12-31`;

// Retrieves needed data from the html, loops over green squares with 1+ contributions,
// and produces a multi-line string that can be run as a bash command.
const script = parse(res.data)
.querySelectorAll("[data-count]")
.map((el) => {
return {
date: el.attributes["data-date"],
count: parseInt(el.attributes["data-count"]),
};
})
.filter((contribution) => contribution.count > 0)
.map((contribution) => getCommand(contribution))
.join("")
.concat("git pull origin main\n", "git push -f origin main");
if (input.git === 'gitlab') {
const api_uri = `${input.username}/users/${input.username}/activity?from=${input.year}-12-01&to=${input.year}-12-31`;
}

fs.writeFile("script.sh", script, () => {
console.log("\nFile was created successfully.");
// Returns contribution graph html for a full selected year.
const res = await axios.get(api_uri);

if (input.execute) {
console.log("This might take a moment!\n");
shell.exec("sh ./script.sh");
}
});
// Retrieves needed data from the html, loops over green squares with 1+ contributions,
// and produces a multi-line string that can be run as a bash command.
const script = parse(res.data)
.querySelectorAll("[data-count]")
.map((el) => {
return {
date: el.attributes["data-date"],
count: parseInt(el.attributes["data-count"]),
};
})
.filter((contribution) => contribution.count > 0)
.map((contribution) => getCommand(contribution))
.join("")
.concat("git pull origin main\n", "git push -f origin main");

fs.writeFile("script.sh", script, () => {
console.log("\nFile was created successfully.");

if (input.execute) {
console.log("This might take a moment!\n");
shell.exec("sh ./script.sh");
}
});
};
99 changes: 57 additions & 42 deletions src/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,65 @@ import axios from "axios";
console.log("\nHello there!\n");

const questions = [
{
type: "input",
name: "username",
message:
"Please enter GitHub nickname with which you'd like to sync contributions:",
validate: (value) =>
axios
.get(`https://api.github.com/users/${value}`)
.then(() => true)
.catch(() => "Please enter an existing GitHub username."),
},
{
type: "input",
name: "year",
message: "What year would you like to sync?",
default() {
return new Date().getFullYear();
{
type: "input",
name: "git",
message: "Please enter the type of Git server with which you'd like to sync contributions: `github` or `gitlab`",
choices: ['github', 'gitlab'],
default() {
return 'github';
},
},
{
type: "input",
name: "gituri",
message:
"Please enter Github/Gitlab server (no trailing slash) with which you'd like to sync contributions:",
validate: (value) =>
axios
.get(`${value}`)
.then(() => true)
.catch(() => "Please enter an existing (or accessible) GitHub/GitLab server."),
},
{
type: "input",
name: "username",
message:
"Please enter GitHub nickname with which you'd like to sync contributions:",
},
{
type: "input",
name: "year",
message: "What year would you like to sync?",
default() {
return new Date().getFullYear();
},
},
{
type: "list",
message: "How would you like this to happen?",
name: "execute",
choices: [
{
name: `Generate a bash script & execute it immediately.\n Note: it *will* push to origin main and it would be difficult to undo.`,
value: true,
},
{
name: "Only generate, no execution.",
value: false,
},
],
default: () => false,
},
{
type: "confirm",
name: "confirm",
message: "Ready to proceed?",
},
},
{
type: "list",
message: "How would you like this to happen?",
name: "execute",
choices: [
{
name: `Generate a bash script & execute it immediately.\n Note: it *will* push to origin main and it would be difficult to undo.`,
value: true,
},
{
name: "Only generate, no execution.",
value: false,
},
],
default: () => false,
},
{
type: "confirm",
name: "confirm",
message: "Ready to proceed?",
},
];

inquirer.prompt(questions).then((answers) => {
if (answers.confirm) {
script(answers);
}
if (answers.confirm) {
script(answers);
}
});