11import { error } from '@sveltejs/kit' ;
22import { dataDirContainsData , dataDirIsInit , getDataDir } from './data/dataDir' ;
33import simpleGit , { type FileStatusResult } from 'simple-git' ;
4- import { appendFile , readdir } from 'fs/promises' ;
4+ import fs from 'fs/promises' ;
55import { rimraf } from 'rimraf' ;
6+ import { spawn } from 'child-process-promise' ;
7+ import os from 'os' ;
8+ import { fileExists } from '.' ;
9+
10+ /** Path to SSH directory */
11+ const SSH_DIR = `${ os . homedir ( ) } /.ssh` ;
12+
13+ /** Path to the SSH known hosts file */
14+ const KNOWN_HOSTS_FILE = `${ os . homedir ( ) } /.ssh/known_hosts` ;
615
716const DEFAULT_GITIGNORE = `
817config.local.json
@@ -26,6 +35,47 @@ export interface RepoStatus {
2635 changes : FileStatusResult [ ] ,
2736}
2837
38+ /** Returns whether the given URL requires SSH */
39+ export function urlRequiresSsh ( url : string ) : boolean {
40+ return (
41+ url . includes ( '@' )
42+ && url . includes ( ':' )
43+ ) ;
44+ }
45+
46+ /**
47+ * Run an ssh-keyscan command for the host at the given URL.
48+ *
49+ * Eg given URL "git@host.com:path/to/repo", we should extract:
50+ * ^^^^^^^^
51+ */
52+ export async function runSshKeyscan ( url : string ) {
53+ // FIXME: This probably doesn't work in some cases
54+ const host = url . split ( '@' , 2 ) [ 1 ] . split ( ':' , 1 ) [ 0 ] ;
55+
56+ // mkdir -p ~/.ssh
57+ await fs . mkdir ( SSH_DIR ) . catch ( ( ) => { } ) ;
58+
59+ // Check if ~/.ssh/known_hosts already has this host in it
60+ if ( await fileExists ( KNOWN_HOSTS_FILE ) ) {
61+ const hostsContent = await fs . readFile ( KNOWN_HOSTS_FILE , { encoding : 'utf-8' } ) ;
62+ for ( const line of hostsContent . split ( / \r ? \n / ) ) {
63+ if ( line . startsWith ( `${ host } ` ) ) {
64+ // Host is already known
65+ return ;
66+ }
67+ }
68+ }
69+
70+ const process = await spawn ( 'ssh-keyscan' , [ host ] , { capture : [ 'stdout' ] } ) ;
71+
72+ console . log ( process . stdout ) ;
73+ console . log ( typeof process . stdout ) ;
74+
75+ // Now add to ~/.ssh/known_hosts
76+ await fs . appendFile ( KNOWN_HOSTS_FILE , process . stdout , { encoding : 'utf-8' } ) ;
77+ }
78+
2979/** Return status info for repo */
3080export async function getRepoStatus ( ) : Promise < RepoStatus > {
3181 const repo = simpleGit ( getDataDir ( ) ) ;
@@ -63,14 +113,15 @@ export async function setupGitRepo(repo: string, branch: string | null) {
63113
64114 try {
65115 await simpleGit ( ) . clone ( repo , dir , options ) ;
66- } catch ( e ) {
116+ } catch ( e : any ) {
117+ console . log ( e ) ;
67118 throw error ( 400 , `${ e } ` ) ;
68119 }
69120
70121 // If there are files in the repo, we should validate that it is a proper
71122 // portfolio data repo.
72123 // Ignore .git, since it is included in empty repos too.
73- if ( ( await readdir ( getDataDir ( ) ) ) . find ( f => f !== '.git' ) ) {
124+ if ( ( await fs . readdir ( getDataDir ( ) ) ) . find ( f => f !== '.git' ) ) {
74125 if ( ! await dataDirContainsData ( ) ) {
75126 // Clean up and delete repo before giving error
76127 await rimraf ( getDataDir ( ) ) ;
@@ -87,5 +138,8 @@ export async function setupGitRepo(repo: string, branch: string | null) {
87138
88139/** Set up a default gitignore */
89140export async function setupGitignore ( ) {
90- await appendFile ( `${ getDataDir ( ) } /.gitignore` , DEFAULT_GITIGNORE , { encoding : 'utf-8' } ) ;
141+ // TODO: Skip this step if the gitignore already ignores all contents
142+ // probably worth finding a library to deal with this, since it is
143+ // complicated
144+ await fs . appendFile ( `${ getDataDir ( ) } /.gitignore` , DEFAULT_GITIGNORE , { encoding : 'utf-8' } ) ;
91145}
0 commit comments