Skip to content

Commit 41a20bc

Browse files
committed
[WIP] Implement push command
1 parent fd80e97 commit 41a20bc

3 files changed

Lines changed: 62 additions & 112 deletions

File tree

bin/helper.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import GitHelper from "./lib/git.js";
1010
import DGitHelper from "./lib/dgit.js";
1111
import LineHelper from "./lib/line.js";
1212
import Arweave from "arweave";
13-
import { getRefsOnArweave } from "./lib/arweave.js";
13+
import { getRefsOnArweave, pushGitObject, updateRef } from "./lib/arweave.js";
1414

1515
const _timeout = async (duration) => {
1616
return new Promise((resolve, reject) => {
@@ -48,6 +48,7 @@ export default class Helper {
4848
// address and path shortcuts
4949
this.address = this.url.split("://")[1];
5050
this.path = path.resolve(process.env.GIT_DIR || "");
51+
this.arweaveWalletPath = process.env.ARWEAVE_WALLET_PATH;
5152
// config
5253
this.config = this._config();
5354
// lib
@@ -144,6 +145,14 @@ export default class Helper {
144145
async _handlePush(line) {
145146
this.debug("cmd", line);
146147

148+
if (!this.arweaveWalletPath) {
149+
console.error("Missing ARWEAVE_WALLET_PATH env variable");
150+
this._die();
151+
}
152+
153+
const rawdata = fs.readFileSync(this.arweaveWalletPath);
154+
this.wallet = JSON.parse(rawdata);
155+
147156
while (true) {
148157
const [src, dst] = line.split(" ")[1].split(":");
149158

@@ -243,7 +252,7 @@ export default class Helper {
243252
.stdout.split("\n")
244253
.slice(0, -1)
245254
.map((object) => object.substr(0, 40));
246-
console.error(objects);
255+
247256
// checking permissions
248257
try {
249258
spinner = ora(`Checking permissions over ${this.address}`).start();
@@ -281,17 +290,15 @@ export default class Helper {
281290
"Collecting git objects [this may take a while]"
282291
).start();
283292

284-
for (const commit of commits) {
285-
const _mapping = await this.git.collect(commit, mapping);
286-
mapping = { ...mapping, ..._mapping };
293+
for (const oid of objects) {
294+
const object = await this.git.load(oid);
295+
// Check object already exists on arweave before pushing
296+
puts.push(
297+
pushGitObject(this._arweave, this.wallet, this.url, oid, object)
298+
);
287299
}
288300

289-
head = commits[0];
290-
291-
// tslint:disable-next-line:forin
292-
for (const entry in mapping) {
293-
puts.push(this.dgit.put(mapping[entry]));
294-
}
301+
head = objects[0];
295302

296303
spinner.succeed("Git objects collected");
297304
} catch (err) {
@@ -301,20 +308,23 @@ export default class Helper {
301308

302309
// upload git objects
303310
try {
304-
spinner = ora("Uploading git objects to IPFS").start();
311+
spinner = ora("Uploading git objects to arweave").start();
305312
await Promise.all(puts);
306-
spinner.succeed("Git objects uploaded to IPFS");
313+
spinner.succeed("Git objects uploaded to arweave");
307314
} catch (err) {
308-
spinner.fail("Failed to upload git objects to IPFS: " + err.message);
315+
spinner.fail(
316+
"Failed to upload git objects to arweave: " + err.message
317+
);
309318
this._die();
310319
}
311320

312321
// register on chain
313322
try {
314-
spinner = ora(`Registering ref ${dst} ${head} on-chain`).start();
323+
spinner = ora(`Updating ref ${dst} ${head} on arweave`).start();
324+
await updateRef(this._arweave, this.wallet, this.url, dst, head);
315325
} catch (err) {
316326
spinner.fail(
317-
`Failed to register ref ${dst} ${head} on-chain: ` + err.message
327+
`Failed to update ref ${dst} ${head} on arweave: ` + err.message
318328
);
319329
this._die();
320330
}

bin/lib/arweave.js

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ export function parseArgitRemoteURI(remoteURI) {
3636
function addTransactionTags(tx, repo, txType) {
3737
tx.addTag("Repo", repo);
3838
tx.addTag("Type", txType);
39-
// tx.addTag("Content-Type", "application/json");
4039
tx.addTag("App-Name", "dgit");
4140
tx.addTag("version", "0.0.1");
4241
tx.addTag("Unix-Time", Math.round(new Date().getTime() / 1000)); // Add Unix timestamp
@@ -92,38 +91,37 @@ export async function getRef(arweave, remoteURI, name) {
9291
return tx_rows[0].oid;
9392
}
9493

95-
export async function pushGitObject(arweave, wallet, remoteURI, oid, type) {
94+
export async function pushGitObject(arweave, wallet, remoteURI, oid, object) {
9695
const { repoName } = parseArgitRemoteURI(remoteURI);
9796

98-
let tx = await arweave.createTransaction({ data: packfile.packfile }, wallet);
99-
tx = addTransactionTags(tx, repoName, "send-pack");
97+
let tx = await arweave.createTransaction({ data: object }, wallet);
98+
tx = addTransactionTags(tx, repoName, "push-git-object");
10099
tx.addTag("oid", oid);
101-
tx.addTag("oldoid", oldoid);
102-
tx.addTag("filename", packfile.filename);
100+
tx.addTag("Content-Type", "application/octet-stream");
103101

104102
await arweave.transactions.sign(tx, wallet);
105103
let uploader = await arweave.transactions.getUploader(tx);
106104

107105
while (!uploader.isComplete) {
108106
await uploader.uploadChunk();
109-
console.log(
107+
console.error(
110108
`${uploader.pctComplete}% complete, ${uploader.uploadedChunks}/${uploader.totalChunks}`
111109
);
112110
}
111+
}
113112

114-
// Send fee to PST holders
115-
const contractState = await smartweave.readContract(arweave, contractId);
116-
const holder = smartweave.selectWeightedPstHolder(contractState.balances);
117-
// send a fee. You should inform the user about this fee and amount.
118-
const pstTx = await arweave.createTransaction(
119-
{ target: holder, quantity: arweave.ar.arToWinston("0.01") },
120-
wallet
121-
);
122-
pstTx.addTag("App-Name", "dgit");
123-
pstTx.addTag("version", "0.0.1");
124-
125-
await arweave.transactions.sign(pstTx, wallet);
126-
await arweave.transactions.post(pstTx);
113+
export async function fetchGitObject(arweave, remoteURI, oid) {
114+
const query = {
115+
op: "and",
116+
expr1: repoQuery(remoteURI),
117+
expr2: {
118+
op: "and",
119+
expr1: { op: "equals", expr1: "oid", expr2: oid },
120+
expr2: { op: "equals", expr1: "Type", expr2: "push-git-object" },
121+
},
122+
};
123+
const txids = await arweave.arql(query);
124+
return await arweave.transactions.getData(txids[0], { decode: true });
127125
}
128126

129127
export async function pushPackfile(

bin/lib/git.js

Lines changed: 18 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import npath from "path";
44
import shell from "shelljs";
55
// tslint:disable-next-line:no-submodule-imports
66
import gitP from "simple-git/promise.js";
7-
import pkg from "smart-buffer";
8-
const { SmartBuffer } = pkg;
9-
import zlib from "zlib";
7+
8+
import { fetchGitObject } from "./arweave.js";
109

1110
const git = gitP();
1211

@@ -20,36 +19,8 @@ export default class GitHelper {
2019
/***** core methods *****/
2120

2221
// OK
23-
async collect(oid, mapping) {
22+
async collect(oid) {
2423
this.debug("collecting", oid);
25-
26-
if (mapping[oid]) return mapping;
27-
28-
const node = await this.load(oid);
29-
30-
if (node.gitType === "commit") {
31-
// node is a commit
32-
const _mapping = await this.collect(
33-
this.helper.ipld.cidToSha(node.tree["/"]),
34-
mapping
35-
);
36-
return { ...mapping, ..._mapping, ...{ [cid]: node } };
37-
} else if (Buffer.isBuffer(node)) {
38-
// node is a blob
39-
return { ...mapping, ...{ [cid]: node } };
40-
} else {
41-
// node is a tree
42-
// tslint:disable-next-line:forin
43-
for (const entry in node) {
44-
const _mapping = await this.collect(
45-
this.helper.ipld.cidToSha(node[entry].hash["/"]),
46-
mapping
47-
);
48-
mapping = { ...mapping, ..._mapping };
49-
}
50-
51-
return { ...mapping, ...{ [cid]: node } };
52-
}
5324
}
5425

5526
// OK
@@ -58,32 +29,16 @@ export default class GitHelper {
5829

5930
if (await this.exists(oid)) return;
6031

61-
// const cid = this.helper.ipld.shaToCid(oid);
62-
// const node = await this.helper.ipld.get(cid);
63-
64-
// if (node.gitType === "commit") {
65-
// // node is a commit
66-
// await this.download(this.helper.ipld.cidToSha(node.tree["/"]));
67-
68-
// for (const parent of node.parents) {
69-
// await this.download(this.helper.ipld.cidToSha(parent["/"]));
70-
// }
71-
72-
// await this.dump(oid, node);
73-
// } else if (Buffer.isBuffer(node)) {
74-
// // node is a blob
75-
// await this.dump(oid, node);
76-
// } else {
77-
// // node is a tree
78-
// // tslint:disable-next-line:forin
79-
// for (const entry in node) {
80-
// await this.download(
81-
// await this.helper.ipld.cidToSha(node[entry].hash["/"])
82-
// );
83-
// }
84-
85-
// await this.dump(oid, node);
86-
// }
32+
const object = await fetchGitObject(
33+
this.helper._arweave,
34+
this.helper.url,
35+
oid
36+
);
37+
38+
await this.dump(oid, object);
39+
40+
// if commit expand the tree
41+
console.error(git.catFile([oid]));
8742
}
8843

8944
/***** fs-related methods *****/
@@ -97,29 +52,16 @@ export default class GitHelper {
9752

9853
// OK
9954
async load(oid) {
100-
const type = shell
101-
.exec(`git cat-file -t ${oid}`, { silent: true })
102-
.stdout.trim();
103-
const size = shell
104-
.exec(`git cat-file -s ${oid}`, { silent: true })
105-
.stdout.trim();
106-
const data = await git.binaryCatFile([type, oid]);
107-
108-
const raw = new SmartBuffer();
109-
raw.writeString(`${type} `);
110-
raw.writeString(size);
111-
raw.writeUInt8(0);
112-
raw.writeBuffer(data);
113-
114-
return this.helper.ipld.deserialize(raw.toBuffer());
55+
const path = await this.path(oid);
56+
await fs.ensureFile(path);
57+
return fs.readFileSync(path);
11558
}
11659

11760
// OK
118-
async dump(oid, node) {
61+
async dump(oid, object) {
11962
const path = await this.path(oid);
120-
const buffer = await this.helper.ipld.serialize(node);
12163
await fs.ensureFile(path);
122-
fs.writeFileSync(path, zlib.deflateSync(buffer));
64+
fs.writeFileSync(path, object);
12365
}
12466

12567
/***** utility methods *****/

0 commit comments

Comments
 (0)