@@ -34,6 +34,10 @@ fn nix_injected_commit_hash() -> Option<String> {
3434 }
3535}
3636
37+ fn is_nix_build ( ) -> bool {
38+ nix_injected_commit_hash ( ) . is_some ( )
39+ }
40+
3741fn find_git_hash ( ) -> String {
3842 nix_injected_commit_hash ( ) . unwrap_or_else ( || {
3943 // When we're *not* building in Nix, we can assume that git metadata is still present in the filesystem,
@@ -156,10 +160,10 @@ fn generate_template_files() {
156160}
157161
158162fn generate_template_entry ( code : & mut String , template_path : & Path , source : & str , manifest_dir : & Path ) {
159- let ( template_files , resolved_base) = list_all_files ( template_path, manifest_dir) ;
163+ let ( git_files , resolved_base) = get_git_tracked_files ( template_path, manifest_dir) ;
160164
161- if template_files . is_empty ( ) {
162- panic ! ( "Template '{}' has no files, check if the path is correct " , source) ;
165+ if git_files . is_empty ( ) {
166+ panic ! ( "Template '{}' has no git-tracked files! Check that the directory exists and contains files tracked by git. " , source) ;
163167 }
164168
165169 // Example: /Users/user/SpacetimeDB
@@ -192,7 +196,7 @@ fn generate_template_entry(code: &mut String, template_path: &Path, source: &str
192196 code. push_str ( " {\n " ) ;
193197 code. push_str ( " let mut files = HashMap::new();\n " ) ;
194198
195- for file_path in template_files {
199+ for file_path in git_files {
196200 // Example file_path: modules/quickstart-chat/src/lib.rs (relative to repo root)
197201 // Example resolved_base: modules/quickstart-chat
198202 // Example relative_path: src/lib.rs
@@ -255,6 +259,18 @@ fn generate_template_entry(code: &mut String, template_path: &Path, source: &str
255259 code. push_str ( " }\n \n " ) ;
256260}
257261
262+ /// Get a list of files tracked by git from a given directory
263+ fn get_git_tracked_files ( path : & Path , manifest_dir : & Path ) -> ( Vec < PathBuf > , PathBuf ) {
264+ if is_nix_build ( ) {
265+ // When building in Nix, we already know that there are no untracked files in our source tree,
266+ // so we just list all of the files.
267+ list_all_files ( path, manifest_dir)
268+ } else {
269+ // When building outside of Nix, we invoke `git` to list all the tracked files.
270+ get_git_tracked_files_via_cli ( path, manifest_dir)
271+ }
272+ }
273+
258274fn list_all_files ( path : & Path , manifest_dir : & Path ) -> ( Vec < PathBuf > , PathBuf ) {
259275 let manifest_dir = manifest_dir. canonicalize ( ) . unwrap_or_else ( |err| {
260276 panic ! (
@@ -330,6 +346,37 @@ fn make_repo_root_relative(full_path: &Path, repo_root: &Path) -> PathBuf {
330346 } )
331347}
332348
349+ fn get_git_tracked_files_via_cli ( path : & Path , manifest_dir : & Path ) -> ( Vec < PathBuf > , PathBuf ) {
350+ let repo_root = get_repo_root ( ) ;
351+ let repo_root = repo_root. canonicalize ( ) . unwrap_or_else ( |err| {
352+ panic ! (
353+ "Failed to canonicalize repo_root path {}: {err:#?}" ,
354+ repo_root. display( ) ,
355+ )
356+ } ) ;
357+
358+ let resolved_path = make_repo_root_relative ( & get_full_path_within_manifest_dir ( path, manifest_dir) , & repo_root) ;
359+
360+ let output = Command :: new ( "git" )
361+ . args ( [ "ls-files" , resolved_path. to_str ( ) . unwrap ( ) ] )
362+ . current_dir ( repo_root)
363+ . output ( )
364+ . expect ( "Failed to execute git ls-files" ) ;
365+
366+ if !output. status . success ( ) {
367+ return ( Vec :: new ( ) , resolved_path) ;
368+ }
369+
370+ let stdout = String :: from_utf8 ( output. stdout ) . unwrap ( ) ;
371+ let files: Vec < PathBuf > = stdout
372+ . lines ( )
373+ . filter ( |line| !line. is_empty ( ) )
374+ . map ( PathBuf :: from)
375+ . collect ( ) ;
376+
377+ ( files, resolved_path)
378+ }
379+
333380fn get_repo_root ( ) -> PathBuf {
334381 let manifest_dir = get_manifest_dir ( ) ;
335382 // Cargo doesn't expose a way to get the workspace root, AFAICT (pgoldman 2025-10-31).
0 commit comments