summaryrefslogtreecommitdiffstats
path: root/hugofs/language_fs.go
diff options
context:
space:
mode:
Diffstat (limited to 'hugofs/language_fs.go')
-rw-r--r--hugofs/language_fs.go346
1 files changed, 0 insertions, 346 deletions
diff --git a/hugofs/language_fs.go b/hugofs/language_fs.go
deleted file mode 100644
index db77c1fab..000000000
--- a/hugofs/language_fs.go
+++ /dev/null
@@ -1,346 +0,0 @@
-// Copyright 2018 The Hugo Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package hugofs
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/spf13/afero"
-)
-
-const hugoFsMarker = "__hugofs"
-
-var (
- _ LanguageAnnouncer = (*LanguageFileInfo)(nil)
- _ FilePather = (*LanguageFileInfo)(nil)
- _ afero.Lstater = (*LanguageFs)(nil)
-)
-
-// LanguageAnnouncer is aware of its language.
-type LanguageAnnouncer interface {
- Lang() string
- TranslationBaseName() string
-}
-
-// FilePather is aware of its file's location.
-type FilePather interface {
- // Filename gets the full path and filename to the file.
- Filename() string
-
- // Path gets the content relative path including file name and extension.
- // The directory is relative to the content root where "content" is a broad term.
- Path() string
-
- // RealName is FileInfo.Name in its original form.
- RealName() string
-
- BaseDir() string
-}
-
-// LanguageDirsMerger implements the afero.DirsMerger interface, which is used
-// to merge two directories.
-var LanguageDirsMerger = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) {
- m := make(map[string]*LanguageFileInfo)
-
- for _, fi := range lofi {
- fil, ok := fi.(*LanguageFileInfo)
- if !ok {
- return nil, fmt.Errorf("received %T, expected *LanguageFileInfo", fi)
- }
- m[fil.virtualName] = fil
- }
-
- for _, fi := range bofi {
- fil, ok := fi.(*LanguageFileInfo)
- if !ok {
- return nil, fmt.Errorf("received %T, expected *LanguageFileInfo", fi)
- }
- existing, found := m[fil.virtualName]
-
- if !found || existing.weight < fil.weight {
- m[fil.virtualName] = fil
- }
- }
-
- merged := make([]os.FileInfo, len(m))
- i := 0
- for _, v := range m {
- merged[i] = v
- i++
- }
-
- return merged, nil
-}
-
-// LanguageFileInfo is a super-set of os.FileInfo with additional information
-// about the file in relation to its Hugo language.
-type LanguageFileInfo struct {
- os.FileInfo
- lang string
- baseDir string
- realFilename string
- relFilename string
- name string
- realName string
- virtualName string
- translationBaseName string
-
- // We add some weight to the files in their own language's content directory.
- weight int
-}
-
-// Filename returns a file's real filename including the base (ie.
-// "/my/base/sect/page.md").
-func (fi *LanguageFileInfo) Filename() string {
- return fi.realFilename
-}
-
-// Path returns a file's filename relative to the base (ie. "sect/page.md").
-func (fi *LanguageFileInfo) Path() string {
- return fi.relFilename
-}
-
-// RealName returns a file's real base name (ie. "page.md").
-func (fi *LanguageFileInfo) RealName() string {
- return fi.realName
-}
-
-// BaseDir returns a file's base directory (ie. "/my/base").
-func (fi *LanguageFileInfo) BaseDir() string {
- return fi.baseDir
-}
-
-// Lang returns a file's language (ie. "sv").
-func (fi *LanguageFileInfo) Lang() string {
- return fi.lang
-}
-
-// TranslationBaseName returns the base filename without any extension or language
-// identifiers (ie. "page").
-func (fi *LanguageFileInfo) TranslationBaseName() string {
- return fi.translationBaseName
-}
-
-// Name is the name of the file within this filesystem without any path info.
-// It will be marked with language information so we can identify it as ours
-// (ie. "__hugofs_sv_page.md").
-func (fi *LanguageFileInfo) Name() string {
- return fi.name
-}
-
-type languageFile struct {
- afero.File
- fs *LanguageFs
-}
-
-// Readdir creates FileInfo entries by calling Lstat if possible.
-func (l *languageFile) Readdir(c int) (ofi []os.FileInfo, err error) {
- names, err := l.File.Readdirnames(c)
- if err != nil {
- return nil, err
- }
-
- fis := make([]os.FileInfo, len(names))
-
- for i, name := range names {
- fi, _, err := l.fs.LstatIfPossible(filepath.Join(l.Name(), name))
-
- if err != nil {
- return nil, err
- }
- fis[i] = fi
- }
-
- return fis, err
-}
-
-// LanguageFs represents a language filesystem.
-type LanguageFs struct {
- // This Fs is usually created with a BasePathFs
- basePath string
- lang string
- nameMarker string
- languages map[string]bool
- afero.Fs
-}
-
-// NewLanguageFs creates a new language filesystem.
-func NewLanguageFs(lang string, languages map[string]bool, fs afero.Fs) *LanguageFs {
- if lang == "" {
- panic("no lang set for the language fs")
- }
- var basePath string
-
- if bfs, ok := fs.(*afero.BasePathFs); ok {
- basePath, _ = bfs.RealPath("")
- }
-
- marker := hugoFsMarker + "_" + lang + "_"
-
- return &LanguageFs{lang: lang, languages: languages, basePath: basePath, Fs: fs, nameMarker: marker}
-}
-
-// Lang returns a language filesystem's language (ie. "sv").
-func (fs *LanguageFs) Lang() string {
- return fs.lang
-}
-
-// Stat returns the os.FileInfo of a given file.
-func (fs *LanguageFs) Stat(name string) (os.FileInfo, error) {
- name, err := fs.realName(name)
- if err != nil {
- return nil, err
- }
-
- fi, err := fs.Fs.Stat(name)
- if err != nil {
- return nil, err
- }
-
- return fs.newLanguageFileInfo(name, fi)
-}
-
-// Open opens the named file for reading.
-func (fs *LanguageFs) Open(name string) (afero.File, error) {
- name, err := fs.realName(name)
- if err != nil {
- return nil, err
- }
- f, err := fs.Fs.Open(name)
-
- if err != nil {
- return nil, err
- }
- return &languageFile{File: f, fs: fs}, nil
-}
-
-// LstatIfPossible returns the os.FileInfo structure describing a given file.
-// It attempts to use Lstat if supported or defers to the os. In addition to
-// the FileInfo, a boolean is returned telling whether Lstat was called.
-func (fs *LanguageFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
- name, err := fs.realName(name)
- if err != nil {
- return nil, false, err
- }
-
- var fi os.FileInfo
- var b bool
-
- if lif, ok := fs.Fs.(afero.Lstater); ok {
- fi, b, err = lif.LstatIfPossible(name)
- } else {
- fi, err = fs.Fs.Stat(name)
- }
-
- if err != nil {
- return nil, b, err
- }
-
- lfi, err := fs.newLanguageFileInfo(name, fi)
-
- return lfi, b, err
-}
-
-func (fs *LanguageFs) realPath(name string) (string, error) {
- if baseFs, ok := fs.Fs.(*afero.BasePathFs); ok {
- return baseFs.RealPath(name)
- }
- return name, nil
-}
-
-func (fs *LanguageFs) realName(name string) (string, error) {
- if strings.Contains(name, hugoFsMarker) {
- if !strings.Contains(name, fs.nameMarker) {
- return "", os.ErrNotExist
- }
- return strings.Replace(name, fs.nameMarker, "", 1), nil
- }
-
- if fs.basePath == "" {
- return name, nil
- }
-
- return strings.TrimPrefix(name, fs.basePath), nil
-}
-
-func (fs *LanguageFs) newLanguageFileInfo(filename string, fi os.FileInfo) (*LanguageFileInfo, error) {
- filename = filepath.Clean(filename)
- _, name := filepath.Split(filename)
-
- realName := name
- virtualName := name
-
- realPath, err := fs.realPath(filename)
- if err != nil {
- return nil, err
- }
-
- lang := fs.Lang()
-
- baseNameNoExt := ""
-
- if !fi.IsDir() {
-
- // Try to extract the language from the file name.
- // Any valid language identificator in the name will win over the
- // language set on the file system, e.g. "mypost.en.md".
- baseName := filepath.Base(name)
- ext := filepath.Ext(baseName)
- baseNameNoExt = baseName
-
- if ext != "" {
- baseNameNoExt = strings.TrimSuffix(baseNameNoExt, ext)
- }
-
- fileLangExt := filepath.Ext(baseNameNoExt)
- fileLang := strings.TrimPrefix(fileLangExt, ".")
-
- if fs.languages[fileLang] {
- lang = fileLang
- baseNameNoExt = strings.TrimSuffix(baseNameNoExt, fileLangExt)
- }
-
- // This connects the filename to the filesystem, not the language.
- virtualName = baseNameNoExt + "." + lang + ext
-
- name = fs.nameMarker + name
- }
-
- weight := 1
- // If this file's language belongs in this directory, add some weight to it
- // to make it more important.
- if lang == fs.Lang() {
- weight = 2
- }
-
- if fi.IsDir() {
- // For directories we always want to start from the union view.
- realPath = strings.TrimPrefix(realPath, fs.basePath)
- }
-
- return &LanguageFileInfo{
- lang: lang,
- weight: weight,
- realFilename: realPath,
- realName: realName,
- relFilename: strings.TrimPrefix(strings.TrimPrefix(realPath, fs.basePath), string(os.PathSeparator)),
- name: name,
- virtualName: virtualName,
- translationBaseName: baseNameNoExt,
- baseDir: fs.basePath,
- FileInfo: fi}, nil
-}