<commit_before>package config

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"path/filepath"

	"github.com/polyglottis/email"
)

var path = flag.String("c", "config.json", "Path to configuration file")

var config = new(Config)

func init() {
	flag.Parse()

	f, err := ioutil.ReadFile(*path)
	if err != nil {
		if abs, err := filepath.Abs(*path); err == nil {
			log.Printf("Unable to read config file [%s]: %v", abs, err)
		} else {
			log.Printf("Unable to read config file: %v", err)
		}
	}

	err = json.Unmarshal(f, config)
	if err != nil {
		log.Fatalln("Error parsing config file:", err)
	}

	err = config.initMailUser()
	if err != nil {
		log.Println("Error initializing email user:", err)
	}
}

func Get() *Config {
	return config
}

type Config struct {
	// Databases
	ContentDB  string // path to content database
	LanguageDB string // path to language database
	UserDB     string // path to user database

	// Web
	HttpServer      string // main http server
	TemplateRoot    string // path to templates files
	SessionKeyPath  string // path to session keys file (the file will be automatically created if not present)
	EmailConfigPath string // path to email (smtp) server configuration file (this file must contain a json-encoded github.com/polyglottis/email.User)
	StaticDir       string // optional: if present, the server also serves static files from there

	// Optional, only for distributed version over rpc:
	Frontend   string // frontend server
	Content    string // content server
	User       string // user server
	Language   string // language server
	ContentOp  string // content operations server
	UserOp     string // user operations server
	LanguageOp string // language operations server

	MailUser *email.User // will be populated
}

func (c *Config) initMailUser() error {
	if c.EmailConfigPath == "" {
		return fmt.Errorf("Missing EmailConfigPath in config file")
	}
	f, err := ioutil.ReadFile(c.EmailConfigPath)
	if err != nil {
		return err
	}
	user := new(email.User)
	err = json.Unmarshal(f, user)
	if err != nil {
		return err
	}
	config.MailUser = user
	return nil
}
<commit_msg>Lazy-loading config (otherwise flag.Parse occurs too early)<commit_after>package config

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"path/filepath"

	"github.com/polyglottis/email"
)

var path = flag.String("c", "config.json", "Path to configuration file")

var config *Config

func read() {
	flag.Parse()

	f, err := ioutil.ReadFile(*path)
	if err != nil {
		if abs, err := filepath.Abs(*path); err == nil {
			log.Printf("Unable to read config file [%s]: %v", abs, err)
		} else {
			log.Printf("Unable to read config file: %v", err)
		}
	}

	err = json.Unmarshal(f, config)
	if err != nil {
		log.Fatalln("Error parsing config file:", err)
	}

	err = config.initMailUser()
	if err != nil {
		log.Println("Error initializing email user:", err)
	}
}

func Get() *Config {
	if config == nil {
		config = new(Config)
		read()
	}
	return config
}

type Config struct {
	// Databases
	ContentDB  string // path to content database
	LanguageDB string // path to language database
	UserDB     string // path to user database

	// Web
	HttpServer      string // main http server
	TemplateRoot    string // path to templates files
	SessionKeyPath  string // path to session keys file (the file will be automatically created if not present)
	EmailConfigPath string // path to email (smtp) server configuration file (this file must contain a json-encoded github.com/polyglottis/email.User)
	StaticDir       string // optional: if present, the server also serves static files from there

	// Optional, only for distributed version over rpc:
	Frontend   string // frontend server
	Content    string // content server
	User       string // user server
	Language   string // language server
	ContentOp  string // content operations server
	UserOp     string // user operations server
	LanguageOp string // language operations server

	MailUser *email.User // will be populated
}

func (c *Config) initMailUser() error {
	if c.EmailConfigPath == "" {
		return fmt.Errorf("Missing EmailConfigPath in config file")
	}
	f, err := ioutil.ReadFile(c.EmailConfigPath)
	if err != nil {
		return err
	}
	user := new(email.User)
	err = json.Unmarshal(f, user)
	if err != nil {
		return err
	}
	config.MailUser = user
	return nil
}

{'fraction_non_alphanumeric': 0.10896994723560449, 'fraction_numerical': 0.0, 'mean_word_length': 3.3512974051896207, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2794606', 'n_tokens_mistral': 1402, 'n_tokens_neox': 1351, 'n_words': 484}