aboutsummaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* Copy sent emails to the Sent folderDrew DeVault2019-05-1511-20/+132
| | | | Or rather, to a user-specified folder
* Fix default bindings for quit and editDrew DeVault2019-05-141-1/+4
|
* Move ! bind to [messages]Drew DeVault2019-05-141-1/+1
|
* Add (non-functional) reply commands to bindingsDrew DeVault2019-05-141-2/+9
|
* Add ! to default keybindingsDrew DeVault2019-05-141-0/+1
|
* Implement move, mv commandsDrew DeVault2019-05-143-6/+65
|
* Force INBOX to be included in dirlistDrew DeVault2019-05-141-0/+11
|
* Implement :copy (aka :cp)Drew DeVault2019-05-147-3/+101
|
* Implement abort commandCole Helbling2019-05-141-0/+23
| | | | | This allows the user to close the compose tab without sending their current composition.
* Update tab name as subject changesDrew DeVault2019-05-145-10/+40
| | | | Also moves truncation to the tab widget
* Add $EDITOR, internal config for composeDrew DeVault2019-05-144-6/+30
|
* Add IRC link to README.mdDrew DeVault2019-05-141-0/+2
|
* Remove tab before going asyncDrew DeVault2019-05-141-1/+1
| | | | To prevent repeated attempts to send
* Add distinct keybindings for each compose viewDrew DeVault2019-05-146-14/+51
|
* Send emails asyncronouslyDrew DeVault2019-05-141-47/+73
|
* Implement sending emails /o/Drew DeVault2019-05-144-24/+160
|
* Add :send-message, prepares & writes email to /tmpDrew DeVault2019-05-145-6/+121
|
* Remove leftover debug loggingDrew DeVault2019-05-131-3/+0
|
* Handle external message deletionsDrew DeVault2019-05-132-1/+7
|
* Handle incoming emails gracefullyDrew DeVault2019-05-135-9/+36
|
* Spec out review message screenDrew DeVault2019-05-132-9/+61
|
* Populate "From" header from config for new emailsDrew DeVault2019-05-135-14/+31
|
* Add outgoing account configurationDrew DeVault2019-05-122-5/+10
|
* Implement :{next,prev}-field in compose viewDrew DeVault2019-05-126-5/+70
|
* Expand compose focus handling a bitDrew DeVault2019-05-121-19/+30
|
* Add initial compose widgetDrew DeVault2019-05-127-3/+169
|
* Move aerc to dedicated mailing listDrew DeVault2019-05-111-1/+1
|
* "Press any key to close" for completed processesDrew DeVault2019-05-112-1/+10
|
* Refactor ctx stashing out of exlineDrew DeVault2019-05-112-8/+4
|
* Split ex line text handling into dedicated widgetDrew DeVault2019-05-114-107/+163
|
* lib/ui: fix UI.Exit race conditionSimon Ser2019-05-052-4/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | UI.Exit can be accessed from goroutines drawing, goroutines executing commands and goroutines waiting for events. Write at 0x00c0002b2040 by main goroutine: main.main.func1() /home/simon/src/aerc2/aerc.go:76 +0x33d git.sr.ht/~sircmpwn/aerc2/widgets.(*Aerc).BeginExCommand.func1() /home/simon/src/aerc2/widgets/aerc.go:245 +0x89 git.sr.ht/~sircmpwn/aerc2/widgets.(*ExLine).Event() /home/simon/src/aerc2/widgets/exline.go:131 +0x442 git.sr.ht/~sircmpwn/aerc2/widgets.(*Aerc).Event() /home/simon/src/aerc2/widgets/aerc.go:116 +0x83c git.sr.ht/~sircmpwn/aerc2/widgets.(*Aerc).simulate() /home/simon/src/aerc2/widgets/aerc.go:109 +0x12a git.sr.ht/~sircmpwn/aerc2/widgets.(*Aerc).Event() /home/simon/src/aerc2/widgets/aerc.go:142 +0x722 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*UI).Tick() /home/simon/src/aerc2/lib/ui/ui.go:75 +0x33f main.main() /home/simon/src/aerc2/aerc.go:94 +0x497 Previous read at 0x00c0002b2040 by goroutine 19: git.sr.ht/~sircmpwn/aerc2/lib/ui.Initialize.func1() /home/simon/src/aerc2/lib/ui/ui.go:45 +0x97 Goroutine 19 (running) created at: git.sr.ht/~sircmpwn/aerc2/lib/ui.Initialize() /home/simon/src/aerc2/lib/ui/ui.go:44 +0x372 main.main() /home/simon/src/aerc2/aerc.go:87 +0x3a9
* lib/ui: fix Grid race conditionSimon Ser2019-05-051-1/+20
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This was is more complicated than others. The cells list is accessed by multiple goroutines: - Some change the Grid's contents via AddChild/RemoveChild - Some call Draw - Some invalidate the grid via Invalidate Invalidate calls are tricky to handle because they will also invalidate all child cells. This will inturn trigger the cellInvalidated callback, which needs to read the list of cells. For this reason, we use a sync.RWLock which allows multiple concurrent reads. Below is the race fixed by this commit. Read at 0x00c0000bc3d0 by goroutine 7: git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Grid).cellInvalidated() /home/simon/src/aerc2/lib/ui/grid.go:181 +0x45 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Grid).cellInvalidated-fm() /home/simon/src/aerc2/lib/ui/grid.go:179 +0x55 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate() /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Bordered).contentInvalidated-fm() /home/simon/src/aerc2/lib/ui/borders.go:39 +0x56 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate() /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85 git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList.func1() /home/simon/src/aerc2/widgets/dirlist.go:81 +0x55 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate() /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85 git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start.func1() /home/simon/src/aerc2/widgets/spinner.go:88 +0x82 Previous write at 0x00c0000bc3d0 by main goroutine: [failed to restore the stack] Goroutine 7 (running) created at: git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start() /home/simon/src/aerc2/widgets/spinner.go:46 +0x98 git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList() /home/simon/src/aerc2/widgets/dirlist.go:37 +0x28b git.sr.ht/~sircmpwn/aerc2/widgets.NewAccountView() /home/simon/src/aerc2/widgets/account.go:49 +0x5ca git.sr.ht/~sircmpwn/aerc2/widgets.NewAerc() /home/simon/src/aerc2/widgets/aerc.go:60 +0x807 main.main() /home/simon/src/aerc2/aerc.go:65 +0x33e
* lib/msgstore: protect with a mutexSimon Ser2019-04-292-3/+40
| | | | | | MessageStore has a lot of exported fields that can be read from the outside. Each read must be protected, because a call from Update could happen at any time.
* widgets/msglist: fix MessageList.store raceSimon Ser2019-04-291-23/+32
| | | | | This field could be written to in the middle of a Draw call, which reads it multiple times. Use an atomic variable instead.
* worker/imap: use the IMAP connection from a single goroutineSimon Ser2019-04-293-86/+77
| | | | | | | | | | | | | Unfortunately, the IMAP protocol hasn't been designed to be used from multiple goroutines at the same time. For instance, if you fetch twice the same message from two different goroutines, it's not possible to tell whether the response is for one receiver or the other. For this reason, go-imap clients aren't safe to use from multiple goroutines. This commit changes the IMAP workers to be synchronous again (a command is executed only after the previous one has completed). To use IMAP from different threads, popular clients (e.g. Thunderbird) typically open multiple connections.
* Update go-imap to 1.0.0-beta.4Simon Ser2019-04-292-47/+29
| | | | This release contains race conditions fixes.
* lib/ui: fix GridCell.invalid raceSimon Ser2019-04-291-5/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is read/written from different goroutines. Write at 0x00c00009c6f0 by goroutine 7: git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Grid).cellInvalidated() /home/simon/src/aerc2/lib/ui/grid.go:189 +0x122 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Grid).cellInvalidated-fm() /home/simon/src/aerc2/lib/ui/grid.go:178 +0x55 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate() /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Bordered).contentInvalidated-fm() /home/simon/src/aerc2/lib/ui/borders.go:39 +0x56 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate() /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85 git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList.func1() /home/simon/src/aerc2/widgets/dirlist.go:81 +0x55 git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate() /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85 git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start.func1() /home/simon/src/aerc2/widgets/spinner.go:88 +0x82 Previous write at 0x00c00009c6f0 by main goroutine: [failed to restore the stack] Goroutine 7 (running) created at: git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start() /home/simon/src/aerc2/widgets/spinner.go:46 +0x98 git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList() /home/simon/src/aerc2/widgets/dirlist.go:37 +0x28b git.sr.ht/~sircmpwn/aerc2/widgets.NewAccountView() /home/simon/src/aerc2/widgets/account.go:49 +0x5ca git.sr.ht/~sircmpwn/aerc2/widgets.NewAerc() /home/simon/src/aerc2/widgets/aerc.go:60 +0x807 main.main() /home/simon/src/aerc2/aerc.go:65 +0x33e
* lib/ui: introduce InvalidatableSimon Ser2019-04-2712-127/+82
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Many Drawable implementations have their own Invalidate and OnInvalidate functions, with an unexported onInvalidate field. However OnInvalidate and Invalidate are usually not called in the same goroutine. This results in a race on this field, e.g.: Read at 0x00c000094748 by goroutine 7: git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList.func1() /home/simon/src/aerc2/widgets/dirlist.go:85 +0x56 git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start.func1() /home/simon/src/aerc2/widgets/spinner.go:93 +0x1bb Previous write at 0x00c000094748 by main goroutine: [failed to restore the stack] Goroutine 7 (running) created at: git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start() /home/simon/src/aerc2/widgets/spinner.go:46 +0x8f git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList() /home/simon/src/aerc2/widgets/dirlist.go:37 +0x286 git.sr.ht/~sircmpwn/aerc2/widgets.NewAccountView() /home/simon/src/aerc2/widgets/account.go:50 +0x5ca git.sr.ht/~sircmpwn/aerc2/widgets.NewAerc() /home/simon/src/aerc2/widgets/aerc.go:60 +0x800 main.main() /home/simon/src/aerc2/aerc.go:65 +0x33e To fix this, introduce a new type, Invalidatable, which protects the field. Unfortunately the Drawable must be passed to the callback function in Invalidate, so we still need to re-implement this in each Invalidatable user.
* worker/types: fix Worker.Callbacks race conditionSimon Ser2019-04-272-21/+42
| | | | | | | | | | | | | Worker.Process* functions were called in different goroutines than Worker.Post*. Protect the map with a mutex. Also make the map unexported to prevent external unprotected accesses. Worker.Process* functions used to delete items from the map. However they didn't delete the element they retrieved: callbacks[msg.InResponseTo()] was read while callbacks[msg] was deleted. I'm not sure I understand why. I tried to delete the element that was accessed - but this broke everything (UI froze at "Connecting..."). I don't believe any elements were actually removed from the map, so the new code just doesn't remove anything.
* widgets/spinner: fix Spinner.frame raceSimon Ser2019-04-271-12/+15
| | | | | | | | | | | | | | | | | | | | | | | | It's accessed by the goroutine which increments it and the goroutine that draws the widget at the same time. Use atomic instead. Write at 0x00c00000ebc0 by goroutine 7: git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start.func1() /home/simon/src/aerc2/widgets/spinner.go:50 +0x169 Previous read at 0x00c00000ebc0 by main goroutine: [failed to restore the stack] Goroutine 7 (running) created at: git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start() /home/simon/src/aerc2/widgets/spinner.go:44 +0x8b git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList() /home/simon/src/aerc2/widgets/dirlist.go:37 +0x286 git.sr.ht/~sircmpwn/aerc2/widgets.NewAccountView() /home/simon/src/aerc2/widgets/account.go:50 +0x5ca git.sr.ht/~sircmpwn/aerc2/widgets.NewAerc() /home/simon/src/aerc2/widgets/aerc.go:60 +0x800 main.main() /home/simon/src/aerc2/aerc.go:65 +0x33e
* go get git.sr.ht/~sircmpwn/go-libvtermElias Naur2019-04-212-1/+5
| | | | Signed-off-by: Elias Naur <mail@eliasnaur.com>
* Fix segfault on :select-message for unloaded messagesTom Lebreux2019-04-171-0/+3
| | | | Signed-off-by: Tom Lebreux <tomlebreux@cock.li>
* Re-render terminal on invalidateDrew DeVault2019-04-151-4/+13
|
* Fix segfault on :view-message for unloaded messageTom Lebreux2019-04-102-0/+10
| | | | | | This also fixes segfault on :view-message on empty directory Signed-off-by: Tom Lebreux <tomlebreux@cock.li>
* Lowercase MIME types while matching filtersGokberk Yaltirakli2019-04-071-1/+2
|
* Clear damage on each terminal.Draw callDrew DeVault2019-04-051-0/+2
|
* Fix wrong row due to typoTom Lebreux2019-04-051-1/+1
| | | | Signed-off-by: Tom Lebreux <tomlebreux@cock.li>
* Fix infinite loop on empty DirectoryContentsTom Lebreux2019-04-051-2/+4
| | | | | | | | | When changing to an empty directory, ml.selected is 0, and the length of ml.store.Uids is 0. The loop condition is always true so we have an infinite loop causing 100% CPU usage and prevents us to change to other directories. Signed-off-by: Tom Lebreux <tomlebreux@cock.li>
* Show (no messages) for empty foldersDrew DeVault2019-04-041-0/+6
|
* Use better regex for identifying patchesDrew DeVault2019-03-311-1/+1
|