]> git.wincent.com - wincent.git/blob - src/Fig/operations/template.ts
feat: hand-roll stat implementation
[wincent.git] / src / Fig / operations / template.ts
1 import * as fs from 'fs';
2
3 import ErrorWithMetadata from '../../ErrorWithMetadata';
4 import {log} from '../../console';
5 import expand from '../../expand';
6 import run from '../../run';
7 import stat from '../../stat';
8 import {compile, fill} from '../../template';
9 import Context from '../Context';
10 import compare from '../compare';
11
12 export default async function template({
13   force,
14   group,
15   mode,
16   owner,
17   path,
18   src,
19   variables = {},
20 }: {
21   force?: boolean;
22   group?: string;
23   path: string;
24   mode?: Mode;
25   owner?: string;
26   src: string;
27   variables: Variables;
28 }): Promise<void> {
29   const target = expand(path);
30
31   log.info(`template ${src} -> ${target}`);
32
33   const contents = (await Context.compile(src)).fill({variables});
34
35   const diff = await compare({
36     contents,
37     force,
38     group,
39     mode,
40     owner,
41     path: target,
42     state: 'file',
43   });
44
45   console.log(diff);
46
47   if (owner && owner !== Context.attributes.username) {
48     log.notice(`needs sudo: ${Context.attributes.username} -> ${owner}`);
49     const passphrase = await Context.sudoPassphrase;
50     const result = await run('ls', ['-l', '/var/audit'], {passphrase});
51
52     if (result.status !== 0) {
53       throw new ErrorWithMetadata(`Failed command`, {
54         ...result,
55         error: result.error?.toString() ?? null,
56       });
57     }
58
59     // chown in node works with numeric uid and gid
60   } else {
61     // open, write, mode
62     // can't chown, i think? without uid and gid
63
64     // TODO extract this somewhere else
65     // need low-level filesystem ops that are consumed by the high-level
66     // user-accessible ops
67     let current;
68
69     if (fs.existsSync(target)) {
70       current = fs.readFileSync(target, 'utf8');
71
72       if (current !== contents) {
73         log.info('change!');
74       } else {
75         log.info('no change');
76       }
77     }
78   }
79 }