aboutsummaryrefslogtreecommitdiff
path: root/bindings/go
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/go')
-rw-r--r--bindings/go/Makefile70
-rw-r--r--bindings/go/cmds/Makefile11
-rw-r--r--bindings/go/pkg/Makefile17
-rw-r--r--bindings/go/src/notmuch-addrlookup/addrlookup.go (renamed from bindings/go/cmds/notmuch-addrlookup.go)90
-rw-r--r--bindings/go/src/notmuch/notmuch.go (renamed from bindings/go/pkg/notmuch.go)142
5 files changed, 162 insertions, 168 deletions
diff --git a/bindings/go/Makefile b/bindings/go/Makefile
index aba2d59..c38f234 100644
--- a/bindings/go/Makefile
+++ b/bindings/go/Makefile
@@ -1,30 +1,40 @@
-# Copyright 2009 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.
-
-include ${GOROOT}/src/Make.inc
-
-all: install
-
-DIRS=\
- pkg\
- cmds\
-
-
-clean.dirs: $(addsuffix .clean, $(DIRS))
-install.dirs: $(addsuffix .install, $(DIRS))
-nuke.dirs: $(addsuffix .nuke, $(DIRS))
-test.dirs: $(addsuffix .test, $(TEST))
-bench.dirs: $(addsuffix .bench, $(BENCH))
-
-%.clean:
- +cd $* && $(QUOTED_GOBIN)/gomake clean
-
-%.install:
- +cd $* && $(QUOTED_GOBIN)/gomake install
-
-clean: clean.dirs
-
-install: install.dirs
-
-#-include ${GOROOT}/src/Make.deps
+# Makefile for the go bindings of notmuch
+
+export GOPATH ?= $(shell pwd)
+export CGO_CFLAGS ?= -I../../../../lib
+export CGO_LDFLAGS ?= -L../../../../lib
+
+GO ?= go
+GOFMT ?= gofmt
+
+all: notmuch notmuch-addrlookup
+
+.PHONY: notmuch
+notmuch:
+ $(GO) install notmuch
+
+.PHONY: goconfig
+goconfig:
+ if [ ! -d src/github.com/kless/goconfig/config ]; then \
+ $(GO) get github.com/kless/goconfig/config; \
+ fi
+
+.PHONY: notmuch-addrlookup
+notmuch-addrlookup: notmuch goconfig
+ $(GO) install notmuch-addrlookup
+
+.PHONY: format
+format:
+ $(GOFMT) -w=true $(GOFMT_OPTS) src/notmuch
+ $(GOFMT) -w=true $(GOFMT_OPTS) src/notmuch-addrlookup
+
+.PHONY: check-format
+check-format:
+ $(GOFMT) -d=true $(GOFMT_OPTS) src/notmuch
+ $(GOFMT) -d=true $(GOFMT_OPTS) src/notmuch-addrlookup
+
+.PHONY: clean
+clean:
+ $(GO) clean notmuch
+ $(GO) clean notmuch-addrlookup
+ rm -rf pkg bin
diff --git a/bindings/go/cmds/Makefile b/bindings/go/cmds/Makefile
deleted file mode 100644
index afbc6d2..0000000
--- a/bindings/go/cmds/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright 2009 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.
-
-include ${GOROOT}/src/Make.inc
-
-TARG=notmuch-addrlookup
-GOFILES=\
- notmuch-addrlookup.go
-
-include ${GOROOT}/src/Make.cmd
diff --git a/bindings/go/pkg/Makefile b/bindings/go/pkg/Makefile
deleted file mode 100644
index de89dbc..0000000
--- a/bindings/go/pkg/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2009 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.
-
-include $(GOROOT)/src/Make.inc
-
-TARG=notmuch
-CGOFILES=notmuch.go
-CGO_LDFLAGS=-lnotmuch
-
-CLEANFILES+=notmuch_test
-
-include $(GOROOT)/src/Make.pkg
-
-%: install %.go
- $(GC) $*.go
- $(LD) -o $@ $*.$O
diff --git a/bindings/go/cmds/notmuch-addrlookup.go b/bindings/go/src/notmuch-addrlookup/addrlookup.go
index 16958e5..59283f8 100644
--- a/bindings/go/cmds/notmuch-addrlookup.go
+++ b/bindings/go/src/notmuch-addrlookup/addrlookup.go
@@ -22,18 +22,18 @@ type frequencies map[string]uint
/* Used to sort the email addresses from most to least used */
func sort_by_freq(m1, m2 *mail_addr_freq) int {
- if (m1.count[0] == m2.count[0] &&
+ if m1.count[0] == m2.count[0] &&
m1.count[1] == m2.count[1] &&
- m1.count[2] == m2.count[2]) {
+ m1.count[2] == m2.count[2] {
return 0
}
- if (m1.count[0] > m2.count[0] ||
+ if m1.count[0] > m2.count[0] ||
m1.count[0] == m2.count[0] &&
- m1.count[1] > m2.count[1] ||
+ m1.count[1] > m2.count[1] ||
m1.count[0] == m2.count[0] &&
- m1.count[1] == m2.count[1] &&
- m1.count[2] > m2.count[2]) {
+ m1.count[1] == m2.count[1] &&
+ m1.count[2] > m2.count[2] {
return -1
}
@@ -46,17 +46,17 @@ func (self *maddresses) Len() int {
return len(*self)
}
-func (self *maddresses) Less(i,j int) bool {
+func (self *maddresses) Less(i, j int) bool {
m1 := (*self)[i]
m2 := (*self)[j]
- v := sort_by_freq(m1, m2)
- if v<=0 {
+ v := sort_by_freq(m1, m2)
+ if v <= 0 {
return true
}
return false
}
-func (self *maddresses) Swap(i,j int) {
+func (self *maddresses) Swap(i, j int) {
(*self)[i], (*self)[j] = (*self)[j], (*self)[i]
}
@@ -66,7 +66,7 @@ func frequent_fullname(freqs frequencies) string {
fullname := ""
freqs_sz := len(freqs)
- for mail,freq := range freqs {
+ for mail, freq := range freqs {
if (freq > maxfreq && mail != "") || freqs_sz == 1 {
// only use the entry if it has a real name
// or if this is the only entry
@@ -86,33 +86,33 @@ func addresses_by_frequency(msgs *notmuch.Messages, name string, pass uint, addr
// "<?(?P<mail>\\b\\w+([-+.]\\w+)*\\@\\w+[-\\.\\w]*\\.([-\\.\\w]+)*\\w\\b)>?)"
pattern = `.*` + strings.ToLower(name) + `.*`
var re *regexp.Regexp = nil
- var err os.Error = nil
- if re,err = regexp.Compile(pattern); err != nil {
+ var err error = nil
+ if re, err = regexp.Compile(pattern); err != nil {
log.Printf("error: %v\n", err)
return &freqs
}
-
+
headers := []string{"from"}
if pass == 1 {
headers = append(headers, "to", "cc", "bcc")
}
- for ;msgs.Valid();msgs.MoveToNext() {
+ for ; msgs.Valid(); msgs.MoveToNext() {
msg := msgs.Get()
//println("==> msg [", msg.GetMessageId(), "]")
- for _,header := range headers {
+ for _, header := range headers {
froms := strings.ToLower(msg.GetHeader(header))
//println(" froms: ["+froms+"]")
- for _,from := range strings.Split(froms, ",", -1) {
+ for _, from := range strings.Split(froms, ",") {
from = strings.Trim(from, " ")
match := re.FindString(from)
//println(" -> match: ["+match+"]")
- occ,ok := freqs[match]
+ occ, ok := freqs[match]
if !ok {
freqs[match] = 0
occ = 0
}
- freqs[match] = occ+1
+ freqs[match] = occ + 1
}
}
}
@@ -125,7 +125,7 @@ func search_address_passes(queries [3]*notmuch.Query, name string) []string {
addr_to_realname := make(map[string]*frequencies)
var pass uint = 0 // 0-based
- for _,query := range queries {
+ for _, query := range queries {
if query == nil {
//println("**warning: idx [",idx,"] contains a nil query")
continue
@@ -133,9 +133,9 @@ func search_address_passes(queries [3]*notmuch.Query, name string) []string {
msgs := query.SearchMessages()
ht := addresses_by_frequency(msgs, name, pass, &addr_to_realname)
for addr, count := range *ht {
- freq,ok := addr_freq[addr]
+ freq, ok := addr_freq[addr]
if !ok {
- freq = &mail_addr_freq{addr:addr, count:[3]uint{0,0,0}}
+ freq = &mail_addr_freq{addr: addr, count: [3]uint{0, 0, 0}}
}
freq.count[pass] = count
addr_freq[addr] = freq
@@ -154,8 +154,8 @@ func search_address_passes(queries [3]*notmuch.Query, name string) []string {
}
sort.Sort(&addrs)
- for _,addr := range addrs {
- freqs,ok := addr_to_realname[addr.addr]
+ for _, addr := range addrs {
+ freqs, ok := addr_to_realname[addr.addr]
if ok {
val = append(val, frequent_fullname(*freqs))
} else {
@@ -179,7 +179,7 @@ type address_matcher struct {
func new_address_matcher() *address_matcher {
var cfg *config.Config
- var err os.Error
+ var err error
// honor NOTMUCH_CONFIG
home := os.Getenv("NOTMUCH_CONFIG")
@@ -187,30 +187,34 @@ func new_address_matcher() *address_matcher {
home = os.Getenv("HOME")
}
- if cfg,err = config.ReadDefault(path.Join(home, ".notmuch-config")); err != nil {
- log.Fatalf("error loading config file:",err)
+ if cfg, err = config.ReadDefault(path.Join(home, ".notmuch-config")); err != nil {
+ log.Fatalf("error loading config file:", err)
}
- db_path,_ := cfg.String("database", "path")
- primary_email,_ := cfg.String("user", "primary_email")
- addrbook_tag,err := cfg.String("user", "addrbook_tag")
+ db_path, _ := cfg.String("database", "path")
+ primary_email, _ := cfg.String("user", "primary_email")
+ addrbook_tag, err := cfg.String("user", "addrbook_tag")
if err != nil {
addrbook_tag = "addressbook"
}
- self := &address_matcher{db:nil,
- user_db_path:db_path,
- user_primary_email:primary_email,
- user_addrbook_tag:addrbook_tag}
+ self := &address_matcher{db: nil,
+ user_db_path: db_path,
+ user_primary_email: primary_email,
+ user_addrbook_tag: addrbook_tag}
return self
}
func (self *address_matcher) run(name string) {
queries := [3]*notmuch.Query{}
-
+
// open the database
- self.db = notmuch.OpenDatabase(self.user_db_path,
- notmuch.DATABASE_MODE_READ_ONLY)
+ if db, status := notmuch.OpenDatabase(self.user_db_path,
+ notmuch.DATABASE_MODE_READ_ONLY); status == notmuch.STATUS_SUCCESS {
+ self.db = db
+ } else {
+ log.Fatalf("Failed to open the database: %v\n", status)
+ }
// pass 1: look at all from: addresses with the address book tag
query := "tag:" + self.user_addrbook_tag
@@ -222,7 +226,7 @@ func (self *address_matcher) run(name string) {
// pass 2: look at all to: addresses sent from our primary mail
query = ""
if name != "" {
- query = "to:"+name+"*"
+ query = "to:" + name + "*"
}
if self.user_primary_email != "" {
query = query + " from:" + self.user_primary_email
@@ -230,17 +234,17 @@ func (self *address_matcher) run(name string) {
queries[1] = self.db.CreateQuery(query)
// if that leads only to a few hits, we check every from too
- if queries[0].CountMessages() + queries[1].CountMessages() < 10 {
+ if queries[0].CountMessages()+queries[1].CountMessages() < 10 {
query = ""
if name != "" {
- query = "from:"+name+"*"
+ query = "from:" + name + "*"
}
queries[2] = self.db.CreateQuery(query)
}
-
+
// actually retrieve and sort addresses
results := search_address_passes(queries, name)
- for _,v := range results {
+ for _, v := range results {
if v != "" && v != "\n" {
fmt.Println(v)
}
@@ -256,4 +260,4 @@ func main() {
name = os.Args[1]
}
app.run(name)
-} \ No newline at end of file
+}
diff --git a/bindings/go/pkg/notmuch.go b/bindings/go/src/notmuch/notmuch.go
index c6844ef..00bd53a 100644
--- a/bindings/go/pkg/notmuch.go
+++ b/bindings/go/src/notmuch/notmuch.go
@@ -3,6 +3,8 @@
package notmuch
/*
+#cgo LDFLAGS: -lnotmuch
+
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -13,24 +15,26 @@ import "unsafe"
// Status codes used for the return values of most functions
type Status C.notmuch_status_t
+
const (
- STATUS_SUCCESS Status = 0
+ STATUS_SUCCESS Status = iota
STATUS_OUT_OF_MEMORY
- STATUS_READ_ONLY_DATABASE
- STATUS_XAPIAN_EXCEPTION
- STATUS_FILE_ERROR
- STATUS_FILE_NOT_EMAIL
- STATUS_DUPLICATE_MESSAGE_ID
- STATUS_NULL_POINTER
- STATUS_TAG_TOO_LONG
- STATUS_UNBALANCED_FREEZE_THAW
-
- STATUS_LAST_STATUS
+ STATUS_READ_ONLY_DATABASE
+ STATUS_XAPIAN_EXCEPTION
+ STATUS_FILE_ERROR
+ STATUS_FILE_NOT_EMAIL
+ STATUS_DUPLICATE_MESSAGE_ID
+ STATUS_NULL_POINTER
+ STATUS_TAG_TOO_LONG
+ STATUS_UNBALANCED_FREEZE_THAW
+ STATUS_UNBALANCED_ATOMIC
+
+ STATUS_LAST_STATUS
)
func (self Status) String() string {
var p *C.char
-
+
// p is read-only
p = C.notmuch_status_to_string(C.notmuch_status_t(self))
if p != nil {
@@ -80,27 +84,28 @@ type Filenames struct {
}
type DatabaseMode C.notmuch_database_mode_t
+
const (
- DATABASE_MODE_READ_ONLY DatabaseMode = 0
- DATABASE_MODE_READ_WRITE
+ DATABASE_MODE_READ_ONLY DatabaseMode = 0
+ DATABASE_MODE_READ_WRITE
)
// Create a new, empty notmuch database located at 'path'
-func NewDatabase(path string) *Database {
+func NewDatabase(path string) (*Database, Status) {
var c_path *C.char = C.CString(path)
defer C.free(unsafe.Pointer(c_path))
if c_path == nil {
- return nil
+ return nil, STATUS_OUT_OF_MEMORY
}
- self := &Database{db:nil}
- self.db = C.notmuch_database_create(c_path)
- if self.db == nil {
- return nil
+ self := &Database{db: nil}
+ st := Status(C.notmuch_database_create(c_path, &self.db))
+ if st != STATUS_SUCCESS {
+ return nil, st
}
- return self
+ return self, st
}
/* Open an existing notmuch database located at 'path'.
@@ -114,41 +119,41 @@ func NewDatabase(path string) *Database {
* An existing notmuch database can be identified by the presence of a
* directory named ".notmuch" below 'path'.
*
- * The caller should call notmuch_database_close when finished with
+ * The caller should call notmuch_database_destroy when finished with
* this database.
*
* In case of any failure, this function returns NULL, (after printing
* an error message on stderr).
*/
-func OpenDatabase(path string, mode DatabaseMode) *Database {
+func OpenDatabase(path string, mode DatabaseMode) (*Database, Status) {
var c_path *C.char = C.CString(path)
defer C.free(unsafe.Pointer(c_path))
if c_path == nil {
- return nil
+ return nil, STATUS_OUT_OF_MEMORY
}
- self := &Database{db:nil}
- self.db = C.notmuch_database_open(c_path, C.notmuch_database_mode_t(mode))
- if self.db == nil {
- return nil
+ self := &Database{db: nil}
+ st := Status(C.notmuch_database_open(c_path, C.notmuch_database_mode_t(mode), &self.db))
+ if st != STATUS_SUCCESS {
+ return nil, st
}
- return self
+ return self, st
}
/* Close the given notmuch database, freeing all associated
* resources. See notmuch_database_open. */
func (self *Database) Close() {
- C.notmuch_database_close(self.db)
+ C.notmuch_database_destroy(self.db)
}
/* Return the database path of the given database.
*/
func (self *Database) GetPath() string {
-
- /* The return value is a string owned by notmuch so should not be
- * modified nor freed by the caller. */
+
+ /* The return value is a string owned by notmuch so should not be
+ * modified nor freed by the caller. */
var p *C.char = C.notmuch_database_get_path(self.db)
if p != nil {
s := C.GoString(p)
@@ -178,7 +183,6 @@ func (self *Database) NeedsUpgrade() bool {
// TODO: notmuch_database_upgrade
-
/* Retrieve a directory object from the database for 'path'.
*
* Here, 'path' should be a path relative to the path of 'database'
@@ -187,19 +191,20 @@ func (self *Database) NeedsUpgrade() bool {
*
* Can return NULL if a Xapian exception occurs.
*/
-func (self *Database) GetDirectory(path string) *Directory {
+func (self *Database) GetDirectory(path string) (*Directory, Status) {
var c_path *C.char = C.CString(path)
defer C.free(unsafe.Pointer(c_path))
if c_path == nil {
- return nil
+ return nil, STATUS_OUT_OF_MEMORY
}
- c_dir := C.notmuch_database_get_directory(self.db, c_path)
- if c_dir == nil {
- return nil
+ var c_dir *C.notmuch_directory_t
+ st := Status(C.notmuch_database_get_directory(self.db, c_path, &c_dir))
+ if st != STATUS_SUCCESS || c_dir == nil {
+ return nil, st
}
- return &Directory{dir:c_dir}
+ return &Directory{dir: c_dir}, st
}
/* Add a new message to the given notmuch database.
@@ -242,8 +247,7 @@ func (self *Database) GetDirectory(path string) *Directory {
* NOTMUCH_STATUS_READ_ONLY_DATABASE: Database was opened in read-only
* mode so no message can be added.
*/
-func
-(self *Database) AddMessage(fname string) (*Message, Status) {
+func (self *Database) AddMessage(fname string) (*Message, Status) {
var c_fname *C.char = C.CString(fname)
defer C.free(unsafe.Pointer(c_fname))
@@ -254,7 +258,7 @@ func
var c_msg *C.notmuch_message_t = new(C.notmuch_message_t)
st := Status(C.notmuch_database_add_message(self.db, c_fname, &c_msg))
- return &Message{message:c_msg}, st
+ return &Message{message: c_msg}, st
}
/* Remove a message from the given notmuch database.
@@ -282,7 +286,7 @@ func
* mode so no message can be removed.
*/
func (self *Database) RemoveMessage(fname string) Status {
-
+
var c_fname *C.char = C.CString(fname)
defer C.free(unsafe.Pointer(c_fname))
@@ -306,20 +310,21 @@ func (self *Database) RemoveMessage(fname string) Status {
* * An out-of-memory situation occurs
* * A Xapian exception occurs
*/
-func (self *Database) FindMessage(message_id string) *Message {
-
+func (self *Database) FindMessage(message_id string) (*Message, Status) {
+
var c_msg_id *C.char = C.CString(message_id)
defer C.free(unsafe.Pointer(c_msg_id))
if c_msg_id == nil {
- return nil
+ return nil, STATUS_OUT_OF_MEMORY
}
- msg := C.notmuch_database_find_message(self.db, c_msg_id)
- if msg == nil {
- return nil
+ msg := &Message{message: nil}
+ st := Status(C.notmuch_database_find_message(self.db, c_msg_id, &msg.message))
+ if st != STATUS_SUCCESS {
+ return nil, st
}
- return &Message{message:msg}
+ return msg, st
}
/* Return a list of all tags found in the database.
@@ -334,7 +339,7 @@ func (self *Database) GetAllTags() *Tags {
if tags == nil {
return nil
}
- return &Tags{tags:tags}
+ return &Tags{tags: tags}
}
/* Create a new query for 'database'.
@@ -362,7 +367,7 @@ func (self *Database) GetAllTags() *Tags {
* Will return NULL if insufficient memory is available.
*/
func (self *Database) CreateQuery(query string) *Query {
-
+
var c_query *C.char = C.CString(query)
defer C.free(unsafe.Pointer(c_query))
@@ -374,11 +379,12 @@ func (self *Database) CreateQuery(query string) *Query {
if q == nil {
return nil
}
- return &Query{query:q}
+ return &Query{query: q}
}
/* Sort values for notmuch_query_set_sort */
type Sort C.notmuch_sort_t
+
const (
SORT_OLDEST_FIRST Sort = 0
SORT_NEWEST_FIRST
@@ -391,7 +397,7 @@ func (self *Query) String() string {
// FIXME: do we own 'q' or not ?
q := C.notmuch_query_get_query_string(self.query)
//defer C.free(unsafe.Pointer(q))
-
+
if q != nil {
s := C.GoString(q)
return s
@@ -453,7 +459,7 @@ func (self *Query) SearchThreads() *Threads {
if threads == nil {
return nil
}
- return &Threads{threads:threads}
+ return &Threads{threads: threads}
}
/* Execute a query for messages, returning a notmuch_messages_t object
@@ -499,7 +505,7 @@ func (self *Query) SearchMessages() *Messages {
if msgs == nil {
return nil
}
- return &Messages{messages:msgs}
+ return &Messages{messages: msgs}
}
/* Destroy a notmuch_query_t along with any associated resources.
@@ -601,7 +607,7 @@ func (self *Messages) Get() *Message {
if msg == nil {
return nil
}
- return &Message{message:msg}
+ return &Message{message: msg}
}
/* Move the 'messages' iterator to the next message.
@@ -653,7 +659,7 @@ func (self *Messages) CollectTags() *Tags {
if tags == nil {
return nil
}
- return &Tags{tags:tags}
+ return &Tags{tags: tags}
}
/* Get the message ID of 'message'.
@@ -693,14 +699,14 @@ func (self *Message) GetMessageId() string {
* message belongs to a single thread.
*/
func (self *Message) GetThreadId() string {
-
+
if self.message == nil {
return ""
}
id := C.notmuch_message_get_thread_id(self.message)
// we dont own id
// defer C.free(unsafe.Pointer(id))
-
+
if id == nil {
return ""
}
@@ -733,7 +739,7 @@ func (self *Message) GetReplies() *Messages {
if msgs == nil {
return nil
}
- return &Messages{messages:msgs}
+ return &Messages{messages: msgs}
}
/* Get a filename for the email corresponding to 'message'.
@@ -757,7 +763,7 @@ func (self *Message) GetFileName() string {
fname := C.notmuch_message_get_filename(self.message)
// we dont own fname
// defer C.free(unsafe.Pointer(fname))
-
+
if fname == nil {
return ""
}
@@ -766,6 +772,7 @@ func (self *Message) GetFileName() string {
}
type Flag C.notmuch_message_flag_t
+
const (
MESSAGE_FLAG_MATCH Flag = 0
)
@@ -812,16 +819,16 @@ func (self *Message) GetHeader(header string) string {
if self.message == nil {
return ""
}
-
+
var c_header *C.char = C.CString(header)
defer C.free(unsafe.Pointer(c_header))
-
+
/* we dont own value */
value := C.notmuch_message_get_header(self.message, c_header)
if value == nil {
return ""
}
-
+
return C.GoString(value)
}
@@ -863,7 +870,7 @@ func (self *Message) GetTags() *Tags {
if tags == nil {
return nil
}
- return &Tags{tags:tags}
+ return &Tags{tags: tags}
}
/* The longest possible tag value. */
@@ -1120,4 +1127,5 @@ func (self *Filenames) Destroy() {
}
C.notmuch_filenames_destroy(self.fnames)
}
+
/* EOF */