Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 69c091d

Browse files
authored
feat: support mtime-nsecs in mfs cli (#2958)
These are supported in the core and the http interface but got missed off the cli. Fixes #2803
1 parent c2fe4ad commit 69c091d

File tree

8 files changed

+153
-55
lines changed

8 files changed

+153
-55
lines changed

packages/ipfs/src/cli/commands/add.js

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ const getFolderSize = promisify(require('get-folder-size'))
66
const byteman = require('byteman')
77
const mh = require('multihashes')
88
const multibase = require('multibase')
9-
const { createProgressBar } = require('../utils')
9+
const {
10+
createProgressBar,
11+
coerceMtime,
12+
coerceMtimeNsecs
13+
} = require('../utils')
1014
const { cidToString } = require('../../utils/cid')
1115
const globSource = require('ipfs-utils/src/files/glob-source')
1216

@@ -142,32 +146,12 @@ module.exports = {
142146
},
143147
mtime: {
144148
type: 'number',
145-
coerce: (value) => {
146-
value = parseInt(value)
147-
148-
if (isNaN(value)) {
149-
throw new Error('mtime must be a number')
150-
}
151-
152-
return value
153-
},
149+
coerce: coerceMtime,
154150
describe: 'Modification time in seconds before or since the Unix Epoch to apply to created UnixFS entries'
155151
},
156152
'mtime-nsecs': {
157153
type: 'number',
158-
coerce: (value) => {
159-
value = parseInt(value)
160-
161-
if (isNaN(value)) {
162-
throw new Error('mtime-nsecs must be a number')
163-
}
164-
165-
if (value < 0 || value > 999999999) {
166-
throw new Error('mtime-nsecs must be in the range [0,999999999]')
167-
}
168-
169-
return value
170-
},
154+
coerce: coerceMtimeNsecs,
171155
describe: 'Modification time fraction in nanoseconds'
172156
}
173157
},

packages/ipfs/src/cli/commands/files/mkdir.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
const {
44
asBoolean,
55
asOctal,
6-
asDateFromSeconds
6+
asMtimeFromSeconds,
7+
coerceMtime,
8+
coerceMtimeNsecs
79
} = require('../../utils')
810

911
module.exports = {
@@ -49,9 +51,14 @@ module.exports = {
4951
describe: 'Mode to apply to the new directory'
5052
},
5153
mtime: {
52-
type: 'date',
53-
coerce: asDateFromSeconds,
54-
describe: 'Mtime to apply to the new directory in seconds'
54+
type: 'number',
55+
coerce: coerceMtime,
56+
describe: 'Modification time in seconds before or since the Unix Epoch to apply to created UnixFS entries'
57+
},
58+
'mtime-nsecs': {
59+
type: 'number',
60+
coerce: coerceMtimeNsecs,
61+
describe: 'Modification time fraction in nanoseconds'
5562
}
5663
},
5764

@@ -65,7 +72,8 @@ module.exports = {
6572
flush,
6673
shardSplitThreshold,
6774
mode,
68-
mtime
75+
mtime,
76+
mtimeNsecs
6977
} = argv
7078

7179
return ipfs.files.mkdir(path, {
@@ -75,7 +83,7 @@ module.exports = {
7583
flush,
7684
shardSplitThreshold,
7785
mode,
78-
mtime
86+
mtime: asMtimeFromSeconds(mtime, mtimeNsecs)
7987
})
8088
}
8189
}

packages/ipfs/src/cli/commands/files/touch.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
const {
44
asBoolean,
5-
asDateFromSeconds
5+
asMtimeFromSeconds,
6+
coerceMtime,
7+
coerceMtimeNsecs
68
} = require('../../utils')
79

810
module.exports = {
@@ -12,11 +14,15 @@ module.exports = {
1214

1315
builder: {
1416
mtime: {
17+
type: 'number',
1518
alias: 'm',
16-
type: 'date',
17-
coerce: asDateFromSeconds,
18-
default: Date.now(),
19-
describe: 'Time to use as the new modification time'
19+
coerce: coerceMtime,
20+
describe: 'Modification time in seconds before or since the Unix Epoch to apply to created UnixFS entries'
21+
},
22+
'mtime-nsecs': {
23+
type: 'number',
24+
coerce: coerceMtimeNsecs,
25+
describe: 'Modification time fraction in nanoseconds'
2026
},
2127
flush: {
2228
alias: 'f',
@@ -52,11 +58,12 @@ module.exports = {
5258
cidVersion,
5359
hashAlg,
5460
shardSplitThreshold,
55-
mtime
61+
mtime,
62+
mtimeNsecs
5663
} = argv
5764

5865
return ipfs.files.touch(path, {
59-
mtime,
66+
mtime: asMtimeFromSeconds(mtime, mtimeNsecs),
6067
flush,
6168
cidVersion,
6269
hashAlg,

packages/ipfs/src/cli/commands/files/write.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
const {
44
asBoolean,
55
asOctal,
6-
asDateFromSeconds
6+
asMtimeFromSeconds,
7+
coerceMtime,
8+
coerceMtimeNsecs
79
} = require('../../utils')
810

911
module.exports = {
@@ -89,10 +91,14 @@ module.exports = {
8991
describe: 'The mode to use'
9092
},
9193
mtime: {
92-
alias: 'm',
93-
type: 'date',
94-
coerce: asDateFromSeconds,
95-
describe: 'Time to use as the new modification time'
94+
type: 'number',
95+
coerce: coerceMtime,
96+
describe: 'Modification time in seconds before or since the Unix Epoch to apply to created UnixFS entries'
97+
},
98+
'mtime-nsecs': {
99+
type: 'number',
100+
coerce: coerceMtimeNsecs,
101+
describe: 'Modification time fraction in nanoseconds'
96102
}
97103
},
98104

@@ -114,7 +120,8 @@ module.exports = {
114120
flush,
115121
shardSplitThreshold,
116122
mode,
117-
mtime
123+
mtime,
124+
mtimeNsecs
118125
} = argv
119126

120127
await ipfs.files.write(path, getStdin(), {
@@ -132,7 +139,7 @@ module.exports = {
132139
flush,
133140
shardSplitThreshold,
134141
mode,
135-
mtime
142+
mtime: asMtimeFromSeconds(mtime, mtimeNsecs)
136143
})
137144
}
138145
}

packages/ipfs/src/cli/utils.js

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,44 @@ const asOctal = (value) => {
133133
return parseInt(value, 8)
134134
}
135135

136-
const asDateFromSeconds = (value) => {
137-
return new Date(parseInt(value, 10) * 1000)
136+
const asMtimeFromSeconds = (secs, nsecs) => {
137+
if (secs === null || secs === undefined) {
138+
return undefined
139+
}
140+
141+
const output = {
142+
secs
143+
}
144+
145+
if (nsecs !== null && nsecs !== undefined) {
146+
output.nsecs = nsecs
147+
}
148+
149+
return output
150+
}
151+
152+
const coerceMtime = (value) => {
153+
value = parseInt(value)
154+
155+
if (isNaN(value)) {
156+
throw new Error('mtime must be a number')
157+
}
158+
159+
return value
160+
}
161+
162+
const coerceMtimeNsecs = (value) => {
163+
value = parseInt(value)
164+
165+
if (isNaN(value)) {
166+
throw new Error('mtime-nsecs must be a number')
167+
}
168+
169+
if (value < 0 || value > 999999999) {
170+
throw new Error('mtime-nsecs must be in the range [0,999999999]')
171+
}
172+
173+
return value
138174
}
139175

140176
module.exports = {
@@ -148,5 +184,7 @@ module.exports = {
148184
ipfsPathHelp,
149185
asBoolean,
150186
asOctal,
151-
asDateFromSeconds
187+
asMtimeFromSeconds,
188+
coerceMtime,
189+
coerceMtimeNsecs
152190
}

packages/ipfs/test/cli/files/mkdir.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,24 @@ describe('mkdir', () => {
177177
expect(ipfs.files.mkdir.getCall(0).args).to.deep.equal([
178178
path,
179179
defaultOptions({
180-
mtime: new Date(5000)
180+
mtime: {
181+
secs: 5
182+
}
183+
})
184+
])
185+
})
186+
187+
it('should make a directory a different mtime and mtime nsecs', async () => {
188+
await cli(`files mkdir --mtime 5 --mtime-nsecs 10 ${path}`, { ipfs })
189+
190+
expect(ipfs.files.mkdir.callCount).to.equal(1)
191+
expect(ipfs.files.mkdir.getCall(0).args).to.deep.equal([
192+
path,
193+
defaultOptions({
194+
mtime: {
195+
secs: 5,
196+
nsecs: 10
197+
}
181198
})
182199
])
183200
})

packages/ipfs/test/cli/files/touch.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ describe('touch', () => {
2828
}
2929

3030
const path = '/foo'
31-
const mtime = new Date(100000)
31+
const mtime = {
32+
secs: 1000
33+
}
3234
let ipfs
3335

3436
beforeEach(() => {
@@ -40,7 +42,7 @@ describe('touch', () => {
4042
})
4143

4244
it('should update the mtime for a file', async () => {
43-
await cli(`files touch -m ${mtime.getTime() / 1000} ${path}`, { ipfs })
45+
await cli(`files touch -m ${mtime.secs} ${path}`, { ipfs })
4446

4547
expect(ipfs.files.touch.callCount).to.equal(1)
4648
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
@@ -52,7 +54,7 @@ describe('touch', () => {
5254
})
5355

5456
it('should update the mtime without flushing', async () => {
55-
await cli(`files touch -m ${mtime.getTime() / 1000} --flush false ${path}`, { ipfs })
57+
await cli(`files touch -m ${mtime.secs} --flush false ${path}`, { ipfs })
5658

5759
expect(ipfs.files.touch.callCount).to.equal(1)
5860
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
@@ -65,7 +67,7 @@ describe('touch', () => {
6567
})
6668

6769
it('should update the mtime without flushing (short option)', async () => {
68-
await cli(`files touch -m ${mtime.getTime() / 1000} -f false ${path}`, { ipfs })
70+
await cli(`files touch -m ${mtime.secs} -f false ${path}`, { ipfs })
6971

7072
expect(ipfs.files.touch.callCount).to.equal(1)
7173
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
@@ -78,7 +80,7 @@ describe('touch', () => {
7880
})
7981

8082
it('should update the mtime with a different hash algorithm', async () => {
81-
await cli(`files touch -m ${mtime.getTime() / 1000} --hash-alg sha3-256 ${path}`, { ipfs })
83+
await cli(`files touch -m ${mtime.secs} --hash-alg sha3-256 ${path}`, { ipfs })
8284

8385
expect(ipfs.files.touch.callCount).to.equal(1)
8486
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
@@ -91,7 +93,7 @@ describe('touch', () => {
9193
})
9294

9395
it('should update the mtime with a different hash algorithm (short option)', async () => {
94-
await cli(`files touch -m ${mtime.getTime() / 1000} -h sha3-256 ${path}`, { ipfs })
96+
await cli(`files touch -m ${mtime.secs} -h sha3-256 ${path}`, { ipfs })
9597

9698
expect(ipfs.files.touch.callCount).to.equal(1)
9799
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
@@ -104,7 +106,7 @@ describe('touch', () => {
104106
})
105107

106108
it('should update the mtime with a shard split threshold', async () => {
107-
await cli(`files touch -m ${mtime.getTime() / 1000} --shard-split-threshold 10 ${path}`, { ipfs })
109+
await cli(`files touch -m ${mtime.secs} --shard-split-threshold 10 ${path}`, { ipfs })
108110

109111
expect(ipfs.files.touch.callCount).to.equal(1)
110112
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
@@ -115,4 +117,19 @@ describe('touch', () => {
115117
})
116118
])
117119
})
120+
121+
it('should update the mtime and nsecs', async () => {
122+
await cli(`files touch -m 5 --mtime-nsecs 10 ${path}`, { ipfs })
123+
124+
expect(ipfs.files.touch.callCount).to.equal(1)
125+
expect(ipfs.files.touch.getCall(0).args).to.deep.equal([
126+
path,
127+
defaultOptions({
128+
mtime: {
129+
secs: 5,
130+
nsecs: 10
131+
}
132+
})
133+
])
134+
})
118135
})

packages/ipfs/test/cli/files/write.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,27 @@ describe('write', () => {
417417
path,
418418
stdin,
419419
defaultOptions({
420-
mtime: new Date(11000)
420+
mtime: {
421+
secs: 11
422+
}
423+
})
424+
])
425+
})
426+
427+
it('should write to a file with a specified mtime and mtime nsecs', async () => {
428+
const path = '/foo'
429+
430+
await cli(`files write --mtime 11 --mtime-nsecs 10 ${path}`, { ipfs, getStdin })
431+
432+
expect(ipfs.files.write.callCount).to.equal(1)
433+
expect(ipfs.files.write.getCall(0).args).to.deep.equal([
434+
path,
435+
stdin,
436+
defaultOptions({
437+
mtime: {
438+
secs: 11,
439+
nsecs: 10
440+
}
421441
})
422442
])
423443
})

0 commit comments

Comments
 (0)