Skip to content

Commit 4d4db5b

Browse files
tmcgee123phated
authored andcommitted
Support setting setuid/setgid/sticky in updateMetadata (#162)
Adapt tests to support for setuid/setgid/sticky bits Relates to #156
1 parent 20ad7ca commit 4d4db5b

File tree

3 files changed

+109
-9
lines changed

3 files changed

+109
-9
lines changed

lib/fileOperations.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ var isEqual = require('lodash.isequal');
66
var isValidDate = require('vali-date');
77

88
// TODO shared module
9-
// TODO include sticky/setuid/setgid, i.e. 7777?
10-
var MASK_MODE = parseInt('0777', 8);
9+
var MASK_MODE = parseInt('7777', 8);
1110
var DEFAULT_FILE_MODE = parseInt('0666', 8);
1211
var APPEND_MODE_REGEXP = /a/;
1312

test/destModes.js

+82-4
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ function wipeOut() {
2323
});
2424
}
2525

26-
var MASK_MODE = parseInt('777', 8);
26+
var MASK_MODE = parseInt('7777', 8);
2727

2828
function masked(mode) {
2929
return mode & MASK_MODE;
3030
}
3131

3232
var isWindows = (os.platform() === 'win32');
33+
var isDarwin = (os.platform() === 'darwin');
3334

3435
describe('.dest() with custom modes', function() {
3536
beforeEach(wipeOut);
@@ -70,6 +71,46 @@ describe('.dest() with custom modes', function() {
7071
stream.end();
7172
});
7273

74+
75+
76+
it('should set the sticky bit on the mode of a written stream file if set on the vinyl object', function(done) {
77+
if (isWindows) {
78+
this.skip();
79+
return;
80+
}
81+
82+
var inputPath = path.join(__dirname, './fixtures/test.coffee');
83+
var inputBase = path.join(__dirname, './fixtures/');
84+
var expectedPath = path.join(__dirname, './out-fixtures/test.coffee');
85+
var expectedContents = fs.readFileSync(inputPath);
86+
var expectedMode = parseInt('1655', 8);
87+
88+
var contentStream = through.obj();
89+
var expectedFile = new File({
90+
base: inputBase,
91+
cwd: __dirname,
92+
path: inputPath,
93+
contents: contentStream,
94+
stat: {
95+
mode: expectedMode,
96+
},
97+
});
98+
99+
var onEnd = function() {
100+
expect(masked(fs.lstatSync(expectedPath).mode)).toEqual(expectedMode);
101+
done();
102+
};
103+
104+
var stream = vfs.dest('./out-fixtures/', { cwd: __dirname });
105+
stream.on('end', onEnd);
106+
stream.write(expectedFile);
107+
setTimeout(function() {
108+
contentStream.write(expectedContents);
109+
contentStream.end();
110+
}, 100);
111+
stream.end();
112+
});
113+
73114
it('should set the mode of a written stream file if set on the vinyl object', function(done) {
74115
if (isWindows) {
75116
this.skip();
@@ -143,6 +184,41 @@ describe('.dest() with custom modes', function() {
143184
stream.end();
144185
});
145186

187+
it('should set sticky bit on the mode of a written directory if set on the vinyl object', function(done) {
188+
if (isWindows) {
189+
this.skip();
190+
return;
191+
}
192+
193+
var inputPath = path.join(__dirname, './fixtures/test');
194+
var inputBase = path.join(__dirname, './fixtures/');
195+
var expectedPath = path.join(__dirname, './out-fixtures/test');
196+
var expectedMode = parseInt('1655', 8);
197+
198+
var expectedFile = new File({
199+
base: inputBase,
200+
cwd: __dirname,
201+
path: inputPath,
202+
contents: null,
203+
stat: {
204+
isDirectory: function() {
205+
return true;
206+
},
207+
mode: expectedMode,
208+
},
209+
});
210+
211+
var onEnd = function() {
212+
expect(masked(fs.lstatSync(expectedPath).mode)).toEqual(expectedMode);
213+
done();
214+
};
215+
216+
var stream = vfs.dest('./out-fixtures/', { cwd: __dirname });
217+
stream.on('end', onEnd);
218+
stream.write(expectedFile);
219+
stream.end();
220+
});
221+
146222
it('should write new files with the mode specified in options', function(done) {
147223
if (isWindows) {
148224
this.skip();
@@ -255,11 +331,13 @@ describe('.dest() with custom modes', function() {
255331
return;
256332
}
257333

334+
258335
var inputBase = path.join(__dirname, './fixtures');
259336
var inputPath = path.join(__dirname, './fixtures/wow/suchempty');
260337
var expectedBase = path.join(__dirname, './out-fixtures/wow');
261338
var expectedPath = path.join(__dirname, './out-fixtures/wow/suchempty');
262-
var expectedDirMode = parseInt('755', 8);
339+
// NOTE: Darwin does not set setgid
340+
var expectedDirMode = isDarwin ? parseInt('755', 8) : parseInt('2755', 8);
263341
var expectedFileMode = parseInt('655', 8);
264342

265343
var firstFile = new File({
@@ -322,7 +400,7 @@ describe('.dest() with custom modes', function() {
322400
stream.end();
323401
});
324402

325-
it('should see a file with special chmod (setuid/setgid/sticky) as matching', function(done) {
403+
it('should see a file with special chmod (setuid/setgid/sticky) as distinct', function(done) {
326404
if (isWindows) {
327405
this.skip();
328406
return;
@@ -349,7 +427,7 @@ describe('.dest() with custom modes', function() {
349427
});
350428

351429
var onEnd = function() {
352-
expect(fchmodSpy.calls.length).toEqual(0);
430+
expect(fchmodSpy.calls.length).toEqual(1);
353431
done();
354432
};
355433

test/fileOperations.js

+26-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ var updateMetadata = fo.updateMetadata;
2121

2222
var resolution = defaultResolution();
2323

24-
var MASK_MODE = parseInt('777', 8);
24+
var MASK_MODE = parseInt('7777', 8);
2525

2626
function masked(mode) {
2727
return mode & MASK_MODE;
@@ -170,13 +170,13 @@ describe('getModeDiff', function() {
170170
done();
171171
});
172172

173-
it('ignores the sticky/setuid/setgid bits', function(done) {
173+
it('includes the sticky/setuid/setgid bits', function(done) {
174174
var fsMode = parseInt('1777', 8);
175175
var vfsMode = parseInt('4777', 8);
176176

177177
var result = getModeDiff(fsMode, vfsMode);
178178

179-
expect(result).toEqual(0);
179+
expect(result).toEqual(fsMode ^ vfsMode);
180180

181181
done();
182182
});
@@ -795,6 +795,29 @@ describe('updateMetadata', function() {
795795
});
796796
});
797797

798+
799+
it('updates the sticky bit on mode on fs and vinyl object if there is a diff', function(done) {
800+
if (isWindows) {
801+
this.skip();
802+
return;
803+
}
804+
805+
var fchmodSpy = expect.spyOn(fs, 'fchmod').andCallThrough();
806+
807+
var mode = parseInt('1777', 8);
808+
file.stat.mode = mode;
809+
810+
var fd = fs.openSync(inputPath, 'w+');
811+
812+
updateMetadata(fd, file, function(err, fd2) {
813+
expect(fchmodSpy.calls.length).toEqual(1);
814+
var stats = fs.fstatSync(fd);
815+
expect(file.stat.mode).toEqual(stats.mode);
816+
817+
fs.close(fd2, done);
818+
});
819+
});
820+
798821
it('forwards fchmod error and descriptor upon error', function(done) {
799822
if (isWindows) {
800823
this.skip();

0 commit comments

Comments
 (0)