All checks were successful
Tests / unit-tests (push) Successful in 25s
- CreateProject() sa validacijom imena (regex, duplikati, prazno) - POST /projects/create ruta sa AuthMiddleware - Modal forma na projects stranici za unos imena - 10 unit testova za CreateProject - change-password.html template i testovi - Ažuriran TESTING.md sa novom sekcijom Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
1.9 KiB
Go
89 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
type Project struct {
|
|
Name string
|
|
Path string
|
|
Description string
|
|
HasReadme bool
|
|
}
|
|
|
|
// ListProjects returns a sorted list of projects from the given directory.
|
|
// Only directories are considered projects. Hidden directories (starting with .)
|
|
// are excluded.
|
|
func ListProjects(projectsPath string) ([]Project, error) {
|
|
entries, err := os.ReadDir(projectsPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var projects []Project
|
|
for _, e := range entries {
|
|
if !e.IsDir() {
|
|
continue
|
|
}
|
|
name := e.Name()
|
|
if strings.HasPrefix(name, ".") {
|
|
continue
|
|
}
|
|
|
|
p := Project{
|
|
Name: name,
|
|
Path: filepath.Join(projectsPath, name),
|
|
}
|
|
|
|
// Try to read description from README.md first line
|
|
readmePath := filepath.Join(p.Path, "README.md")
|
|
if data, err := os.ReadFile(readmePath); err == nil {
|
|
p.HasReadme = true
|
|
lines := strings.SplitN(string(data), "\n", 3)
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
line = strings.TrimLeft(line, "# ")
|
|
if line != "" {
|
|
p.Description = line
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
projects = append(projects, p)
|
|
}
|
|
|
|
sort.Slice(projects, func(i, j int) bool {
|
|
return projects[i].Name < projects[j].Name
|
|
})
|
|
|
|
return projects, nil
|
|
}
|
|
|
|
var validProjectName = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]*$`)
|
|
|
|
// CreateProject creates a new empty project directory.
|
|
// Name must contain only alphanumeric characters, hyphens, and underscores.
|
|
func CreateProject(projectsPath, name string) error {
|
|
if name == "" {
|
|
return fmt.Errorf("ime projekta ne može biti prazno")
|
|
}
|
|
|
|
if !validProjectName.MatchString(name) {
|
|
return fmt.Errorf("ime projekta može sadržati samo slova, brojeve, '-' i '_'")
|
|
}
|
|
|
|
path := filepath.Join(projectsPath, name)
|
|
|
|
if _, err := os.Stat(path); err == nil {
|
|
return fmt.Errorf("projekat '%s' već postoji", name)
|
|
}
|
|
|
|
return os.MkdirAll(path, 0755)
|
|
}
|