نسخ من khaledmahfouz5/Maqtaa
Add binary files support (#503)
هذا الالتزام موجود في:
89
internal/git/mime.go
Normal file
89
internal/git/mime.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
)
|
||||
|
||||
type MimeType struct {
|
||||
ContentType string
|
||||
}
|
||||
|
||||
func (mt MimeType) IsText() bool {
|
||||
return strings.Contains(mt.ContentType, "text/")
|
||||
}
|
||||
|
||||
func (mt MimeType) IsCSV() bool {
|
||||
return strings.Contains(mt.ContentType, "text/csv")
|
||||
}
|
||||
|
||||
func (mt MimeType) IsImage() bool {
|
||||
return strings.Contains(mt.ContentType, "image/")
|
||||
}
|
||||
|
||||
func (mt MimeType) IsSVG() bool {
|
||||
return strings.Contains(mt.ContentType, "image/svg+xml")
|
||||
}
|
||||
|
||||
func (mt MimeType) IsPDF() bool {
|
||||
return strings.Contains(mt.ContentType, "application/pdf")
|
||||
}
|
||||
|
||||
func (mt MimeType) IsAudio() bool {
|
||||
return strings.Contains(mt.ContentType, "audio/")
|
||||
}
|
||||
|
||||
func (mt MimeType) IsVideo() bool {
|
||||
return strings.Contains(mt.ContentType, "video/")
|
||||
}
|
||||
|
||||
func (mt MimeType) CanBeHighlighted() bool {
|
||||
return mt.IsText() && !mt.IsCSV()
|
||||
}
|
||||
|
||||
func (mt MimeType) CanBeEmbedded() bool {
|
||||
return mt.IsImage() || mt.IsPDF() || mt.IsAudio() || mt.IsVideo()
|
||||
}
|
||||
|
||||
func (mt MimeType) CanBeRendered() bool {
|
||||
return mt.IsText() || mt.IsImage() || mt.IsSVG() || mt.IsPDF() || mt.IsAudio() || mt.IsVideo()
|
||||
}
|
||||
|
||||
func (mt MimeType) CanBeEdited() bool {
|
||||
return mt.IsText() || mt.IsSVG()
|
||||
}
|
||||
|
||||
func (mt MimeType) RenderType() string {
|
||||
t := strings.Split(mt.ContentType, "/")
|
||||
str := ""
|
||||
if len(t) == 2 {
|
||||
str = fmt.Sprintf("(%s)", strings.ToUpper(t[1]))
|
||||
}
|
||||
|
||||
// More user friendly description
|
||||
if mt.IsImage() || mt.IsSVG() {
|
||||
return fmt.Sprintf("Image %s", str)
|
||||
}
|
||||
if mt.IsAudio() {
|
||||
return fmt.Sprintf("Audio %s", str)
|
||||
}
|
||||
if mt.IsVideo() {
|
||||
return fmt.Sprintf("Video %s", str)
|
||||
}
|
||||
if mt.IsPDF() {
|
||||
return "PDF"
|
||||
}
|
||||
if mt.IsCSV() {
|
||||
return "CSV"
|
||||
}
|
||||
if mt.IsText() {
|
||||
return "Text"
|
||||
}
|
||||
return "Binary"
|
||||
}
|
||||
|
||||
func DetectMimeType(data []byte) MimeType {
|
||||
return MimeType{mimetype.Detect(data).String()}
|
||||
}
|
||||
@@ -3,27 +3,23 @@ package git
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
Filename string `json:"filename"`
|
||||
Size uint64 `json:"size"`
|
||||
HumanSize string `json:"human_size"`
|
||||
OldFilename string `json:"-"`
|
||||
Content string `json:"content"`
|
||||
Truncated bool `json:"truncated"`
|
||||
IsCreated bool `json:"-"`
|
||||
IsDeleted bool `json:"-"`
|
||||
}
|
||||
|
||||
type CsvFile struct {
|
||||
File
|
||||
Header []string
|
||||
Rows [][]string
|
||||
Filename string `json:"filename"`
|
||||
Size uint64 `json:"size"`
|
||||
HumanSize string `json:"human_size"`
|
||||
OldFilename string `json:"-"`
|
||||
Content string `json:"content"`
|
||||
Truncated bool `json:"truncated"`
|
||||
IsCreated bool `json:"-"`
|
||||
IsDeleted bool `json:"-"`
|
||||
IsBinary bool `json:"-"`
|
||||
MimeType MimeType `json:"-"`
|
||||
}
|
||||
|
||||
type Commit struct {
|
||||
@@ -62,6 +58,8 @@ func truncateCommandOutput(out io.Reader, maxBytes int64) (string, bool, error)
|
||||
return string(buf), truncated, nil
|
||||
}
|
||||
|
||||
var reLogBinaryNames = regexp.MustCompile(`Binary files (.+) and (.+) differ`)
|
||||
|
||||
// inspired from https://github.com/go-gitea/gitea/blob/main/services/gitdiff/gitdiff.go
|
||||
func parseLog(out io.Reader, maxFiles int, maxBytes int) ([]*Commit, error) {
|
||||
var commits []*Commit
|
||||
@@ -206,6 +204,20 @@ loopLog:
|
||||
currentFile.IsCreated = true
|
||||
case strings.HasPrefix(line, "deleted file"):
|
||||
currentFile.IsDeleted = true
|
||||
case strings.HasPrefix(line, "Binary files"):
|
||||
currentFile.IsBinary = true
|
||||
names := reLogBinaryNames.FindStringSubmatch(line)
|
||||
if names[1][2:] != names[2][2:] {
|
||||
if currentFile.IsCreated {
|
||||
currentFile.Filename = convertOctalToUTF8(names[2])[2:]
|
||||
}
|
||||
if currentFile.IsDeleted {
|
||||
currentFile.Filename = convertOctalToUTF8(names[1])[2:]
|
||||
}
|
||||
} else {
|
||||
currentFile.OldFilename = convertOctalToUTF8(names[1])[2:]
|
||||
currentFile.Filename = convertOctalToUTF8(names[2])[2:]
|
||||
}
|
||||
case strings.HasPrefix(line, "--- "):
|
||||
name := convertOctalToUTF8(line[4 : len(line)-1])
|
||||
if parseRename && currentFile.IsDeleted {
|
||||
@@ -344,27 +356,3 @@ func skipToNextCommit(input *bufio.Reader) (line string, err error) {
|
||||
}
|
||||
return line, err
|
||||
}
|
||||
|
||||
func ParseCsv(file *File) (*CsvFile, error) {
|
||||
|
||||
reader := csv.NewReader(strings.NewReader(file.Content))
|
||||
records, err := reader.ReadAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header := records[0]
|
||||
numColumns := len(header)
|
||||
|
||||
for i := 1; i < len(records); i++ {
|
||||
if len(records[i]) != numColumns {
|
||||
return nil, fmt.Errorf("CSV file has invalid row at index %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
return &CsvFile{
|
||||
File: *file,
|
||||
Header: header,
|
||||
Rows: records[1:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم