github.com/grantbow/bug@v0.3.1/bugs/Bug.go (about)

     1  package bugs
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"regexp"
     8  	"strings"
     9  )
    10  
    11  type Bug struct {
    12  	Dir Directory
    13  }
    14  
    15  type Tag string
    16  
    17  func TitleToDir(title string) Directory {
    18  	replaceWhitespaceWithUnderscore := func(match string) string {
    19  		return strings.Replace(match, " ", "_", -1)
    20  	}
    21  	replaceDashWithMore := func(match string) string {
    22  		if strings.Count(match, " ") > 0 {
    23  			return match
    24  		}
    25  		return "-" + match
    26  	}
    27  
    28  	// Replace sequences of dashes with 1 more dash,
    29  	// as long as there's no whitespace around them
    30  	re := regexp.MustCompile("([\\s]*)(-+)([\\s]*)")
    31  	s := re.ReplaceAllStringFunc(title, replaceDashWithMore)
    32  	// If there are dashes with whitespace around them,
    33  	// replace the whitespace with underscores
    34  	// This is a two step process, because the whitespace
    35  	// can independently be on either side, so it's difficult
    36  	// to do with 1 regex..
    37  	re = regexp.MustCompile("([\\s]+)(-+)")
    38  	s = re.ReplaceAllStringFunc(s, replaceWhitespaceWithUnderscore)
    39  	re = regexp.MustCompile("(-+)([\\s]+)")
    40  	s = re.ReplaceAllStringFunc(s, replaceWhitespaceWithUnderscore)
    41  
    42  	s = strings.Replace(s, " ", "-", -1)
    43  	s = strings.Replace(s, "/", " ", -1)
    44  	return Directory(s)
    45  }
    46  func (b Bug) GetDirectory() Directory {
    47  	return b.Dir
    48  }
    49  
    50  func (b *Bug) LoadBug(dir Directory) {
    51  	b.Dir = dir
    52  
    53  }
    54  
    55  func (b Bug) Title(options string) string {
    56  	var checkOption = func(o string) bool {
    57  		return strings.Contains(options, o)
    58  	}
    59  
    60  	title := b.Dir.GetShortName().ToTitle()
    61  
    62  	if id := b.Identifier(); checkOption("identifier") && id != "" {
    63  		title = fmt.Sprintf("(%s) %s", id, title)
    64  	}
    65  	if strings.Contains(options, "tags") {
    66  		tags := b.StringTags()
    67  		if len(tags) > 0 {
    68  			title += fmt.Sprintf(" (%s)", strings.Join(tags, ", "))
    69  		}
    70  	}
    71  
    72  	priority := checkOption("priority") && b.Priority() != ""
    73  	status := checkOption("status") && b.Status() != ""
    74  	if options == "" {
    75  		priority = false
    76  		status = false
    77  	}
    78  
    79  	if priority && status {
    80  		title += fmt.Sprintf(" (Status: %s; Priority: %s)", b.Status(), b.Priority())
    81  	} else if priority {
    82  		title += fmt.Sprintf(" (Priority: %s)", b.Priority())
    83  	} else if status {
    84  		title += fmt.Sprintf(" (Status: %s)", b.Status())
    85  	}
    86  	return title
    87  }
    88  func (b Bug) Description() string {
    89  	dir := b.GetDirectory()
    90  	desc, err := ioutil.ReadFile(string(dir) + "/Description")
    91  
    92  	if err != nil {
    93  		return "No description provided"
    94  	}
    95  
    96  	return string(desc)
    97  }
    98  func (b Bug) SetDescription(val string) error {
    99  	dir := b.GetDirectory()
   100  
   101  	return ioutil.WriteFile(string(dir)+"/Description", []byte(val), 0644)
   102  }
   103  func (b *Bug) RemoveTag(tag Tag) {
   104  	if dir := b.GetDirectory(); dir != "" {
   105  		os.Remove(string(dir) + "/tags/" + string(tag))
   106  	} else {
   107  		fmt.Printf("Error removing tag: %s", tag)
   108  	}
   109  }
   110  func (b *Bug) TagBug(tag Tag) {
   111  	if dir := b.GetDirectory(); dir != "" {
   112  		os.Mkdir(string(dir)+"/tags/", 0755)
   113  		ioutil.WriteFile(string(dir)+"/tags/"+string(tag), []byte(""), 0644)
   114  	} else {
   115  		fmt.Printf("Error tagging bug: %s", tag)
   116  	}
   117  }
   118  func (b Bug) ViewBug() {
   119  	if identifier := b.Identifier(); identifier != "" {
   120  		fmt.Printf("Identifier: %s\n", identifier)
   121  	}
   122  
   123  	fmt.Printf("Title: %s\n\n", b.Title(""))
   124  	fmt.Printf("Description:\n%s", b.Description())
   125  
   126  	if status := b.Status(); status != "" {
   127  		fmt.Printf("\nStatus: %s", status)
   128  	}
   129  	if priority := b.Priority(); priority != "" {
   130  		fmt.Printf("\nPriority: %s", priority)
   131  	}
   132  	if milestone := b.Milestone(); milestone != "" {
   133  		fmt.Printf("\nMilestone: %s", milestone)
   134  	}
   135  	if tags := b.StringTags(); tags != nil {
   136  		fmt.Printf("\nTags: %s", strings.Join([]string(tags), ", "))
   137  	}
   138  
   139  }
   140  
   141  func (b Bug) StringTags() []string {
   142  	dir := b.GetDirectory()
   143  	dir += "/tags/"
   144  	issues, err := ioutil.ReadDir(string(dir))
   145  	if err != nil {
   146  		return nil
   147  	}
   148  
   149  	tags := make([]string, 0, len(issues))
   150  	for _, issue := range issues {
   151  		tags = append(tags, issue.Name())
   152  	}
   153  	return tags
   154  }
   155  
   156  func (b Bug) HasTag(tag Tag) bool {
   157  	allTags := b.Tags()
   158  	for _, bugTag := range allTags {
   159  		if bugTag == tag {
   160  			return true
   161  		}
   162  	}
   163  	return false
   164  }
   165  func (b Bug) Tags() []Tag {
   166  	dir := b.GetDirectory()
   167  	dir += "/tags/"
   168  	issues, err := ioutil.ReadDir(string(dir))
   169  	if err != nil {
   170  		return nil
   171  	}
   172  
   173  	tags := make([]Tag, 0, len(issues))
   174  	for _, issue := range issues {
   175  		tags = append(tags, Tag(issue.Name()))
   176  	}
   177  	return tags
   178  
   179  }
   180  
   181  func (b Bug) getField(fieldName string) string {
   182  	dir := b.GetDirectory()
   183  	field, err := ioutil.ReadFile(string(dir) + "/" + fieldName)
   184  	if err != nil {
   185  		return ""
   186  	}
   187  	lines := strings.Split(string(field), "\n")
   188  	if len(lines) > 0 {
   189  		return strings.TrimSpace(lines[0])
   190  	}
   191  	return ""
   192  }
   193  
   194  func (b Bug) setField(fieldName, value string) error {
   195  	dir := b.GetDirectory()
   196  	oldValue, err := ioutil.ReadFile(string(dir) + "/" + fieldName)
   197  	var oldLines []string
   198  	if err == nil {
   199  		oldLines = strings.Split(string(oldValue), "\n")
   200  	}
   201  
   202  	newValue := ""
   203  	if len(oldLines) >= 1 {
   204  		// If there were 0 or 1 old lines, overwrite them
   205  		oldLines[0] = value
   206  		newValue = strings.Join(oldLines, "\n")
   207  	} else {
   208  		newValue = value
   209  	}
   210  
   211  	err = ioutil.WriteFile(string(dir)+"/"+fieldName, []byte(newValue), 0644)
   212  	if err != nil {
   213  		return err
   214  	}
   215  	return nil
   216  }
   217  
   218  func (b Bug) Status() string {
   219  	return b.getField("Status")
   220  }
   221  
   222  func (b Bug) SetStatus(newStatus string) error {
   223  	return b.setField("Status", newStatus)
   224  }
   225  func (b Bug) Priority() string {
   226  	return b.getField("Priority")
   227  }
   228  
   229  func (b Bug) SetPriority(newValue string) error {
   230  	return b.setField("Priority", newValue)
   231  }
   232  func (b Bug) Milestone() string {
   233  	return b.getField("Milestone")
   234  }
   235  
   236  func (b Bug) SetMilestone(newValue string) error {
   237  	return b.setField("Milestone", newValue)
   238  }
   239  
   240  func (b Bug) Identifier() string {
   241  	return b.getField("Identifier")
   242  }
   243  
   244  func (b Bug) SetIdentifier(newValue string) error {
   245  	return b.setField("Identifier", newValue)
   246  }