@@ -312,3 +312,54 @@ def is_website_initialized() -> bool:
312312 package_json = website_path / "package.json"
313313
314314 return website_path .exists () and package_json .exists ()
315+
316+
317+ def ensure_website_gitignore_rules () -> None :
318+ """Ensure website-related gitignore rules are present in the project's .gitignore.
319+
320+ Adds the following rules if they don't exist:
321+ - **/_build/ (ignore all build directories)
322+ - !afterpython/_website/src/lib/ (un-ignore website source for customization)
323+ - afterpython/_website.backup/ (ignore backup created by ap update website)
324+ """
325+ import afterpython as ap
326+
327+ gitignore_path = ap .paths .user_path / ".gitignore"
328+
329+ # Rules that should be present
330+ required_rules = [
331+ "**/_build/" ,
332+ "!afterpython/_website/src/lib/" ,
333+ "afterpython/_website.backup/" ,
334+ ]
335+
336+ # Read existing gitignore or create empty list
337+ if gitignore_path .exists ():
338+ existing_lines = gitignore_path .read_text ().splitlines ()
339+ else :
340+ existing_lines = []
341+
342+ # Find which rules are missing
343+ missing_rules = []
344+ for rule in required_rules :
345+ # Check if rule exists (exact match or as part of a line)
346+ if not any (rule in line for line in existing_lines ):
347+ missing_rules .append (rule )
348+
349+ # Add missing rules if any
350+ if missing_rules :
351+ # Ensure file ends with newline if it exists and has content
352+ content = gitignore_path .read_text () if gitignore_path .exists () else ""
353+ if content and not content .endswith ("\n " ):
354+ content += "\n "
355+
356+ # Add a section header if we're adding rules
357+ if content :
358+ content += "\n "
359+ content += "# AfterPython website rules\n "
360+ content += "\n " .join (missing_rules ) + "\n "
361+
362+ gitignore_path .write_text (content )
363+ click .echo (f"Added website-related rules to { gitignore_path } " )
364+ else :
365+ click .echo ("Website gitignore rules already present" )
0 commit comments