hunk.code_window: 		} else if rows, _ := sqlResult.RowsAffected(); rows == 0 {
   			result.Err = model.NewLocAppError("SqlEmojiStore.Delete", "store.sql_emoji.delete.no_results", nil, "id="+id+", err="+err.Error())
   		}
   		storeChannel <- result
   		close(storeChannel)
   	}()
  
hunk.labels: keep keep keep add keep keep keep
hunk.after_edit: 		emojiCache.Remove(id)
  
hunk.file_path: store/sql_emoji_store.go
hunk.type: add
file: // Copyright 2014 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  package webdav
  
  // The If header is covered by Section 10.4.
  // http://www.webdav.org/specs/rfc4918.html#HEADER_If
  
  import (
  	"strings"
  )
  
  // ifHeader is a disjunction (OR) of ifLists.
  type ifHeader struct {
  	lists []ifList
  }
  
  // ifList is a conjunction (AND) of Conditions, and an optional resource tag.
  type ifList struct {
  	resourceTag string
  	conditions  []Condition
  }
  
  // parseIfHeader parses the "If: foo bar" HTTP header. The httpHeader string
  // should omit the "If:" prefix and have any "\r\n"s collapsed to a " ", as is
  // returned by req.Header.Get("If") for a http.Request req.
  func parseIfHeader(httpHeader string) (h ifHeader, ok bool) {
  	s := strings.TrimSpace(httpHeader)
  	switch tokenType, _, _ := lex(s); tokenType {
  	case '(':
  		return parseNoTagLists(s)
  	case angleTokenType:
  		return parseTaggedLists(s)
  	default:
  		return ifHeader{}, false
  	}
  }
  
  func parseNoTagLists(s string) (h ifHeader, ok bool) {
  	for {
  		l, remaining, ok := parseList(s)
  		if !ok {
  			return ifHeader{}, false
  		}
  		h.lists = append(h.lists, l)
  		if remaining == "" {
  			return h, true
  		}
  		s = remaining
  	}
  }
  
  func parseTaggedLists(s string) (h ifHeader, ok bool) {
  	resourceTag, n := "", 0
  	for first := true; ; first = false {
  		tokenType, tokenStr, remaining := lex(s)
  		switch tokenType {
  		case angleTokenType:
  			if !first && n == 0 {
  				return ifHeader{}, false
  			}
  			resourceTag, n = tokenStr, 0
  			s = remaining
  		case '(':
  			n++
  			l, remaining, ok := parseList(s)
  			if !ok {
  				return ifHeader{}, false
  			}
  			l.resourceTag = resourceTag
  			h.lists = append(h.lists, l)
  			if remaining == "" {
  				return h, true
  			}
  			s = remaining
  		default:
  			return ifHeader{}, false
  		}
  	}
  }
  
  func parseList(s string) (l ifList, remaining string, ok bool) {
  	tokenType, _, s := lex(s)
  	if tokenType != '(' {
  		return ifList{}, "", false
  	}
  	for {
  		tokenType, _, remaining = lex(s)
  		if tokenType == ')' {
  			if len(l.conditions) == 0 {
  				return ifList{}, "", false
  			}
  			return l, remaining, true
  		}
  		c, remaining, ok := parseCondition(s)
  		if !ok {
  			return ifList{}, "", false
  		}
  		l.conditions = append(l.conditions, c)
  		s = remaining
  	}
  }
  
  func parseCondition(s string) (c Condition, remaining string, ok bool) {
  	tokenType, tokenStr, s := lex(s)
  	if tokenType == notTokenType {
  		c.Not = true
  		tokenType, tokenStr, s = lex(s)
  	}
  	switch tokenType {
  	case strTokenType, angleTokenType:
  		c.Token = tokenStr
  	case squareTokenType:
  		c.ETag = tokenStr
  	default:
  		return Condition{}, "", false
  	}
  	return c, s, true
  }
  
  // Single-rune tokens like '(' or ')' have a token type equal to their rune.
  // All other tokens have a negative token type.
  const (
  	errTokenType    = rune(-1)
  	eofTokenType    = rune(-2)
  	strTokenType    = rune(-3)
  	notTokenType    = rune(-4)
  	angleTokenType  = rune(-5)
  	squareTokenType = rune(-6)
  )
  
  func lex(s string) (tokenType rune, tokenStr string, remaining string) {
  	// The net/textproto Reader that parses the HTTP header will collapse
  	// Linear White Space that spans multiple "\r\n" lines to a single " ",
  	// so we don't need to look for '\r' or '\n'.
  	for len(s) > 0 && (s[0] == '\t' || s[0] == ' ') {
  		s = s[1:]
  	}
  	if len(s) == 0 {
  		return eofTokenType, "", ""
  	}
  	i := 0
  loop:
  	for ; i < len(s); i++ {
  		switch s[i] {
  		case '\t', ' ', '(', ')', '<', '>', '[', ']':
  			break loop
  		}
  	}
  
  	if i != 0 {
  		tokenStr, remaining = s[:i], s[i:]
  		if tokenStr == "Not" {
  			return notTokenType, "", remaining
  		}
  		return strTokenType, tokenStr, remaining
  	}
  
  	j := 0
  	switch s[0] {
  	case '<':
  		j, tokenType = strings.IndexByte(s, '>'), angleTokenType
  	case '[':
  		j, tokenType = strings.IndexByte(s, ']'), squareTokenType
  	default:
  		return rune(s[0]), "", s[1:]
  	}
  	if j < 0 {
  		return errTokenType, "", ""
  	}
  	return tokenType, s[1:j], s[j+1:]
  }
  