{"thread":{"id":"42569","subject":"[PATCH] Gitk Inotify support","startedAt":"2016-06-16T02:19:50Z","lastAt":"2017-01-01T20:30:40Z","messageCount":5,"participants":["Florian Schüller","Stefan Beller","Paul Mackerras"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"288848","messageId":"CAHdOBFrYWxfSXew5wHwcMym9=s+7cu2E9-MJJe29y+3zV89x7g@mail.gmail.com","threadId":"42569","inReplyTo":null,"subject":"[PATCH] Gitk Inotify support","fromName":"Florian Schüller","fromEmail":"florian.schueller@gmail.com","sentAt":"2016-06-09T21:12:13Z","receivedAt":"2016-06-16T02:19:50Z","isPatch":true,"sender":{"key":"florian.schueller@gmail.com","avatar":"https://gravatar.com/avatar/721f833c626ec2a2f1b8fcc9d4fe9b20ad07cd49637e0487b6b6f14147c0ae95?d=mp&s=160"},"body":"Hi\nIs this correct to send possible gitk patches here? or should I send\nthem to Paul Mackerras somehow?\n\nAnyway I just wanted that gitk automatically updates while I'm working\nin my terminal\n\nAre you interrested?\n\nas described in \"SubmittingPatches\" this patch is based on\ngit://ozlabs.org/~paulus/gitk   22a713c72df8b6799c59287c50cee44c4a6db51e\n\nThe code should be robust to just don't autoupdate if\nhttps://sourceforge.net/projects/tcl-inotify/ is not installed\n\nOpen points for now:\n - release watches for deleted directories seems to cause problems in\ntcl-inotify (so I don't)\n   I'm not sure how often that happens in \".git/\"\n - I only call \"updatecommits\" and I don't know if there is a usecase\nwhere I should be calling \"reloadcommits\"\n\nRegards\nFlorian Schüller\n\n\nFrom 785ed6bc1b4a3b9019d3503b066afb2a025a2bc1 Mon Sep 17 00:00:00 2001\nFrom: =?UTF-8?q?Florian=20Sch=C3=BCller?= <florian.schueller@gmail.com>\nDate: Thu, 9 Jun 2016 22:54:43 +0200\nSubject: [PATCH] first support for inotify\n\n---\n gitk | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 59 insertions(+)\n\ndiff --git a/gitk b/gitk\nindex 805a1c7..6e2ead2 100755\n--- a/gitk\n+++ b/gitk\n@@ -8,6 +8,12 @@ exec wish \"$0\" -- \"$@\"\n # either version 2, or (at your option) any later version.\n \n package require Tk\n+try {\n+    package require inotify\n+    set we_have_inotify true\n+} on error {em} {\n+    set we_have_inotify false\n+}\n \n proc hasworktree {} {\n     return [expr {[exec git rev-parse --is-bare-repository] == \"false\" &&\n@@ -12363,6 +12369,59 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} {\n     }\n }\n \n+proc inotify_handler { fd } {\n+    set events [inotify_watch read]\n+    set watch_info [inotify_watch info]\n+    set update_view false\n+\n+    foreach {event} $events {\n+        set current_watchid [dict get $event watchid]\n+        set flags [dict get $event flags]\n+        set event_filename [dict get $event filename]\n+\n+        foreach {path watchid watch_flags} $watch_info {\n+            if {$watchid eq $current_watchid} {\n+                set watch_path $path\n+            }\n+        }\n+\n+        set full_filename [file join $watch_path $event_filename]\n+\n+#        remove does not seem to work\n+#        if {$flags eq \"s\"} {\n+#            puts \"Remove watch $full_filename\"\n+#            set wd [inotify_watch remove $full_filename]\n+#        }\n+\n+        if {$flags eq \"nD\"} {\n+            set wd [inotify_watch add $full_filename \"nwds\"]\n+        }\n+        if {![string match *.lock $event_filename]} {\n+            set update_view true\n+        }\n+    }\n+\n+    #reloadcommits or updatecommits - depending on file and operation?\n+    if {$update_view} {\n+        updatecommits\n+    }\n+}\n+\n+proc watch_recursive { dir } {\n+    inotify_watch add $dir \"nwaCmMds\"\n+\n+    foreach i [glob -nocomplain -dir $dir *] {\n+        if {[file type $i] eq {directory}} {\n+            watch_recursive $i\n+        }\n+    }\n+}\n+\n+if { $we_have_inotify } {\n+    set fd [inotify create \"inotify_watch\" \"::inotify_handler\"]\n+    watch_recursive $gitdir\n+}\n+\n set nullid \"0000000000000000000000000000000000000000\"\n set nullid2 \"0000000000000000000000000000000000000001\"\n set nullfile \"/dev/null\"\n-- \n2.7.4\n\n"},{"id":"288850","messageId":"CAGZ79kbwrdW=XyPXBNcqBJU1dK8ZvfqyWbgtSt7mvT+m3LQB6g@mail.gmail.com","threadId":"42569","inReplyTo":"CAHdOBFrYWxfSXew5wHwcMym9=s+7cu2E9-MJJe29y+3zV89x7g@mail.gmail.com","subject":"Re: [PATCH] Gitk Inotify support","fromName":"Stefan Beller","fromEmail":"sbeller@google.com","sentAt":"2016-06-09T21:24:44Z","receivedAt":"2016-06-16T02:19:50Z","isPatch":true,"sender":{"key":"stefanbeller@gmail.com","avatar":"https://avatars.githubusercontent.com/u/455868?v=4"},"body":"On Thu, Jun 9, 2016 at 2:12 PM, Florian Schüller\n<florian.schueller@gmail.com> wrote:\n> Hi\n> Is this correct to send possible gitk patches here? or should I send\n> them to Paul Mackerras somehow?\n\nI cc'd Paul for you :)\n\n>\n> Anyway I just wanted that gitk automatically updates while I'm working\n> in my terminal\n\nThanks for coming up with a patch. Welcome to the Git community!\n\n>\n> Are you interrested?\n>\n\nAlso see the section that talks about signing off the patch and how to\nsend the patch\ninline. :)\n\n\n> From 785ed6bc1b4a3b9019d3503b066afb2a025a2bc1 Mon Sep 17 00:00:00 2001\n> From: =?UTF-8?q?Florian=20Sch=C3=BCller?= <florian.schueller@gmail.com>\n> Date: Thu, 9 Jun 2016 22:54:43 +0200\n> Subject: [PATCH] first support for inotify\n\nHere you should describe your change, i.e. what problem is solved in this patch,\nwhat are the alternatives, why is this way the best? Also the sign off\ngoes here.\n\n>\n---\n>  gitk | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 59 insertions(+)\n>\ndiff --git a/gitk b/gitk\n> index 805a1c7..6e2ead2 100755\n> --- a/gitk\n> +++ b/gitk\n> @@ -8,6 +8,12 @@ exec wish \"$0\" -- \"$@\"\n>  # either version 2, or (at your option) any later version.\n>\n>  package require Tk\n> +try {\n> +    package require inotify\n> +    set we_have_inotify true\n> +} on error {em} {\n> +    set we_have_inotify false\n> +}\n\nThere are quite a few \"have_*\" variables, so I would drop the leading \"we_\"\n\n>\n>  proc hasworktree {} {\n>      return [expr {[exec git rev-parse --is-bare-repository] == \"false\" &&\n> @@ -12363,6 +12369,59 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} {\n>      }\n>  }\n>\n> +proc inotify_handler { fd } {\n> +    set events [inotify_watch read]\n> +    set watch_info [inotify_watch info]\n> +    set update_view false\n> +\n> +    foreach {event} $events {\n> +        set current_watchid [dict get $event watchid]\n> +        set flags [dict get $event flags]\n> +        set event_filename [dict get $event filename]\n> +\n> +        foreach {path watchid watch_flags} $watch_info {\n> +            if {$watchid eq $current_watchid} {\n> +                set watch_path $path\n> +            }\n> +        }\n> +\n> +        set full_filename [file join $watch_path $event_filename]\n> +\n> +#        remove does not seem to work\n> +#        if {$flags eq \"s\"} {\n> +#            puts \"Remove watch $full_filename\"\n> +#            set wd [inotify_watch remove $full_filename]\n> +#        }\n\nWhy do we want to carry commented code? I'd drop that.\n\n> +\n> +        if {$flags eq \"nD\"} {\n> +            set wd [inotify_watch add $full_filename \"nwds\"]\n> +        }\n> +        if {![string match *.lock $event_filename]} {\n> +            set update_view true\n> +        }\n> +    }\n> +\n> +    #reloadcommits or updatecommits - depending on file and operation?\n> +    if {$update_view} {\n> +        updatecommits\n> +    }\n> +}\n> +\n> +proc watch_recursive { dir } {\n> +    inotify_watch add $dir \"nwaCmMds\"\n> +\n> +    foreach i [glob -nocomplain -dir $dir *] {\n> +        if {[file type $i] eq {directory}} {\n> +            watch_recursive $i\n> +        }\n> +    }\n> +}\n> +\n> +if { $we_have_inotify } {\n> +    set fd [inotify create \"inotify_watch\" \"::inotify_handler\"]\n> +    watch_recursive $gitdir\n> +}\n> +\n>  set nullid \"0000000000000000000000000000000000000000\"\n>  set nullid2 \"0000000000000000000000000000000000000001\"\n>  set nullfile \"/dev/null\"\n> --\n> 2.7.4\n>\n\nThanks,\nStefan\n"},{"id":"289018","messageId":"CAHdOBFpOm3hf4XPjpSZ0+8rVgyKj+e3qT0cecU4j9ms=+chnDg@mail.gmail.com","threadId":"42569","inReplyTo":"CAGZ79kbwrdW=XyPXBNcqBJU1dK8ZvfqyWbgtSt7mvT+m3LQB6g@mail.gmail.com","subject":"Re: [PATCH] Gitk Inotify support","fromName":"Florian Schüller","fromEmail":"florian.schueller@gmail.com","sentAt":"2016-06-11T14:06:36Z","receivedAt":"2016-06-16T02:19:52Z","isPatch":true,"sender":{"key":"florian.schueller@gmail.com","avatar":"https://gravatar.com/avatar/721f833c626ec2a2f1b8fcc9d4fe9b20ad07cd49637e0487b6b6f14147c0ae95?d=mp&s=160"},"body":"From 74d2f4c1ec560b358fb50b8b7fe8282e7e1457b0 Mon Sep 17 00:00:00 2001\nFrom: =?UTF-8?q?Florian=20Sch=C3=BCller?= <florian.schueller@gmail.com>\nDate: Thu, 9 Jun 2016 22:54:43 +0200\nSubject: [PATCH] first support for inotify\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\n\nJust automatically update gitk when working in a terminal on the same repo\n\nOpen points for now:\n - release watches for deleted directories seems to\n   cause problems in tcl-inotify (so I don't)\n   I'm not sure how often that happens in \".git/\"\n - I only call \"updatecommits\" and I don't know if there is a usecase\n   where I should be calling \"reloadcommits\"\n\nSigned-off-by: Florian Schüller <florian.schueller@gmail.com>\n---\n gitk | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 53 insertions(+)\n\ndiff --git a/gitk b/gitk\nindex 805a1c7..58e3dca 100755\n--- a/gitk\n+++ b/gitk\n@@ -8,6 +8,12 @@ exec wish \"$0\" -- \"$@\"\n # either version 2, or (at your option) any later version.\n\n package require Tk\n+try {\n+    package require inotify\n+    set have_inotify true\n+} on error {em} {\n+    set have_inotify false\n+}\n\n proc hasworktree {} {\n     return [expr {[exec git rev-parse --is-bare-repository] == \"false\" &&\n@@ -12363,6 +12369,53 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} {\n     }\n }\n\n+proc inotify_handler { fd } {\n+    set events [inotify_watch read]\n+    set watch_info [inotify_watch info]\n+    set update_view false\n+\n+    foreach {event} $events {\n+        set current_watchid [dict get $event watchid]\n+        set flags [dict get $event flags]\n+        set event_filename [dict get $event filename]\n+\n+        foreach {path watchid watch_flags} $watch_info {\n+            if {$watchid eq $current_watchid} {\n+                set watch_path $path\n+            }\n+        }\n+\n+        set full_filename [file join $watch_path $event_filename]\n+\n+        if {$flags eq \"nD\"} {\n+            set wd [inotify_watch add $full_filename \"nwds\"]\n+        }\n+        if {![string match *.lock $event_filename]} {\n+            set update_view true\n+        }\n+    }\n+\n+    #reloadcommits or updatecommits - depending on file and operation?\n+    if {$update_view} {\n+        updatecommits\n+    }\n+}\n+\n+proc watch_recursive { dir } {\n+    inotify_watch add $dir \"nwaCmMds\"\n+\n+    foreach i [glob -nocomplain -dir $dir *] {\n+        if {[file type $i] eq {directory}} {\n+            watch_recursive $i\n+        }\n+    }\n+}\n+\n+if { $have_inotify } {\n+    set fd [inotify create \"inotify_watch\" \"::inotify_handler\"]\n+    watch_recursive $gitdir\n+}\n+\n set nullid \"0000000000000000000000000000000000000000\"\n set nullid2 \"0000000000000000000000000000000000000001\"\n set nullfile \"/dev/null\"\n-- \n2.7.4\n\nOn Thu, Jun 9, 2016 at 11:24 PM, Stefan Beller <sbeller@google.com> wrote:\n> On Thu, Jun 9, 2016 at 2:12 PM, Florian Schüller\n> <florian.schueller@gmail.com> wrote:\n>> Hi\n>> Is this correct to send possible gitk patches here? or should I send\n>> them to Paul Mackerras somehow?\n>\n> I cc'd Paul for you :)\n>\n>>\n>> Anyway I just wanted that gitk automatically updates while I'm working\n>> in my terminal\n>\n> Thanks for coming up with a patch. Welcome to the Git community!\n>\n>>\n>> Are you interrested?\n>>\n>\n> Also see the section that talks about signing off the patch and how to\n> send the patch\n> inline. :)\n>\n>\n>> From 785ed6bc1b4a3b9019d3503b066afb2a025a2bc1 Mon Sep 17 00:00:00 2001\n>> From: =?UTF-8?q?Florian=20Sch=C3=BCller?= <florian.schueller@gmail.com>\n>> Date: Thu, 9 Jun 2016 22:54:43 +0200\n>> Subject: [PATCH] first support for inotify\n>\n> Here you should describe your change, i.e. what problem is solved in this patch,\n> what are the alternatives, why is this way the best? Also the sign off\n> goes here.\n>\n>>\n> ---\n>>  gitk | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>>  1 file changed, 59 insertions(+)\n>>\n> diff --git a/gitk b/gitk\n>> index 805a1c7..6e2ead2 100755\n>> --- a/gitk\n>> +++ b/gitk\n>> @@ -8,6 +8,12 @@ exec wish \"$0\" -- \"$@\"\n>>  # either version 2, or (at your option) any later version.\n>>\n>>  package require Tk\n>> +try {\n>> +    package require inotify\n>> +    set we_have_inotify true\n>> +} on error {em} {\n>> +    set we_have_inotify false\n>> +}\n>\n> There are quite a few \"have_*\" variables, so I would drop the leading \"we_\"\n>\n>>\n>>  proc hasworktree {} {\n>>      return [expr {[exec git rev-parse --is-bare-repository] == \"false\" &&\n>> @@ -12363,6 +12369,59 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} {\n>>      }\n>>  }\n>>\n>> +proc inotify_handler { fd } {\n>> +    set events [inotify_watch read]\n>> +    set watch_info [inotify_watch info]\n>> +    set update_view false\n>> +\n>> +    foreach {event} $events {\n>> +        set current_watchid [dict get $event watchid]\n>> +        set flags [dict get $event flags]\n>> +        set event_filename [dict get $event filename]\n>> +\n>> +        foreach {path watchid watch_flags} $watch_info {\n>> +            if {$watchid eq $current_watchid} {\n>> +                set watch_path $path\n>> +            }\n>> +        }\n>> +\n>> +        set full_filename [file join $watch_path $event_filename]\n>> +\n>> +#        remove does not seem to work\n>> +#        if {$flags eq \"s\"} {\n>> +#            puts \"Remove watch $full_filename\"\n>> +#            set wd [inotify_watch remove $full_filename]\n>> +#        }\n>\n> Why do we want to carry commented code? I'd drop that.\n>\n>> +\n>> +        if {$flags eq \"nD\"} {\n>> +            set wd [inotify_watch add $full_filename \"nwds\"]\n>> +        }\n>> +        if {![string match *.lock $event_filename]} {\n>> +            set update_view true\n>> +        }\n>> +    }\n>> +\n>> +    #reloadcommits or updatecommits - depending on file and operation?\n>> +    if {$update_view} {\n>> +        updatecommits\n>> +    }\n>> +}\n>> +\n>> +proc watch_recursive { dir } {\n>> +    inotify_watch add $dir \"nwaCmMds\"\n>> +\n>> +    foreach i [glob -nocomplain -dir $dir *] {\n>> +        if {[file type $i] eq {directory}} {\n>> +            watch_recursive $i\n>> +        }\n>> +    }\n>> +}\n>> +\n>> +if { $we_have_inotify } {\n>> +    set fd [inotify create \"inotify_watch\" \"::inotify_handler\"]\n>> +    watch_recursive $gitdir\n>> +}\n>> +\n>>  set nullid \"0000000000000000000000000000000000000000\"\n>>  set nullid2 \"0000000000000000000000000000000000000001\"\n>>  set nullfile \"/dev/null\"\n>> --\n>> 2.7.4\n>>\n>\n> Thanks,\n> Stefan\n"},{"id":"307482","messageId":"20161212015823.GF18316@fergus.ozlabs.ibm.com","threadId":"42569","inReplyTo":"CAHdOBFpOm3hf4XPjpSZ0+8rVgyKj+e3qT0cecU4j9ms=+chnDg@mail.gmail.com","subject":"Re: [PATCH] Gitk Inotify support","fromName":"Paul Mackerras","fromEmail":"paulus@ozlabs.org","sentAt":"2016-12-12T01:58:23Z","receivedAt":"2016-12-12T01:58:44Z","isPatch":true,"sender":{"key":"paulus@ozlabs.org","avatar":"https://avatars.githubusercontent.com/u/1606439?v=4"},"body":"On Sat, Jun 11, 2016 at 04:06:36PM +0200, Florian Schüller wrote:\n> >From 74d2f4c1ec560b358fb50b8b7fe8282e7e1457b0 Mon Sep 17 00:00:00 2001\n> From: =?UTF-8?q?Florian=20Sch=C3=BCller?= <florian.schueller@gmail.com>\n> Date: Thu, 9 Jun 2016 22:54:43 +0200\n> Subject: [PATCH] first support for inotify\n> MIME-Version: 1.0\n> Content-Type: text/plain; charset=UTF-8\n> Content-Transfer-Encoding: 8bit\n> \n> Just automatically update gitk when working in a terminal on the same repo\n> \n> Open points for now:\n>  - release watches for deleted directories seems to\n>    cause problems in tcl-inotify (so I don't)\n>    I'm not sure how often that happens in \".git/\"\n>  - I only call \"updatecommits\" and I don't know if there is a usecase\n>    where I should be calling \"reloadcommits\"\n\nThanks for the patch.  It's a nice idea.  I think it needs a couple of\nimprovements, though, to make it work even better:\n\n* Some users might not want this behaviour, so we need an option in\n  the preferences pane to enable/disable this.\n\n* I would expect that the updates to the files in .git would come in\n  bursts, so we should probably do something like wait until (say) one\n  second has elapsed since the last notification, without any more\n  notifications, before starting the update.\n\n* We probably want to rate-limit the updates, since on a large tree\n  (e.g. the Linux kernel) the update can take several seconds and the\n  UI is less responsive during that time.\n\nPaul.\n"},{"id":"308601","messageId":"CAHdOBFoOdXxE6dhmGV9fBYCZb9dcfKwhwJzWmxm7aKNkwKYD5Q@mail.gmail.com","threadId":"42569","inReplyTo":"20161212015823.GF18316@fergus.ozlabs.ibm.com","subject":"Re: [PATCH] Gitk Inotify support","fromName":"Florian Schüller","fromEmail":"florian.schueller@gmail.com","sentAt":"2017-01-01T20:30:12Z","receivedAt":"2017-01-01T20:30:40Z","isPatch":true,"sender":{"key":"florian.schueller@gmail.com","avatar":"https://gravatar.com/avatar/721f833c626ec2a2f1b8fcc9d4fe9b20ad07cd49637e0487b6b6f14147c0ae95?d=mp&s=160"},"body":"Just automatically update gitk when working in a terminal on the same repo\n\nThe commit is also on github if that makes things easier\nhttps://github.com/schuellerf/gitk.git\n(inotify branch)\nhttps://github.com/schuellerf/gitk/tree/inotify\n\nFeatures:\n* Detects inotify support\n  if inotify is not detected the options is not available\n  in the preferences\n* Enable/Disable auto update in the preferences\n* Select \"debounce\" time for redraw\n  i.e. the redraw will be postponed for the given time.\n  if a new change is detected in this time the redraw is postponed\n  even more\n* Automatically scroll to the new HEAD after redrawing\n* Depending on the type of change the UI is \"Updated\" or \"Reloaded\"\n\nOpen points for now:\n* release watches for deleted directories seems to\n  cause problems in tcl-inotify (so I don't)\n  I'm not sure how often that happens in \".git/\"\n\nSigned-off-by: Florian Schüller <florian.schueller@gmail.com>\n---\n gitk | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 170 insertions(+), 1 deletion(-)\n\ndiff --git a/gitk b/gitk\nindex a14d7a1..a2850d7 100755\n--- a/gitk\n+++ b/gitk\n@@ -8,6 +8,12 @@ exec wish \"$0\" -- \"$@\"\n # either version 2, or (at your option) any later version.\n\n package require Tk\n+try {\n+    package require inotify\n+    set have_inotify true\n+} on error {em} {\n+    set have_inotify false\n+}\n\n proc hasworktree {} {\n     return [expr {[exec git rev-parse --is-bare-repository] == \"false\" &&\n@@ -11489,6 +11495,7 @@ proc prefspage_general {notebook} {\n     global NS maxwidth maxgraphpct showneartags showlocalchanges\n     global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs\n     global hideremotes want_ttk have_ttk maxrefs\n+    global autoupdate have_inotify autoupdatedebounce\n\n     set page [create_prefs_page $notebook.general]\n\n@@ -11505,13 +11512,21 @@ proc prefspage_general {notebook} {\n     ${NS}::checkbutton $page.showlocal -text [mc \"Show local changes\"] \\\n  -variable showlocalchanges\n     grid x $page.showlocal -sticky w\n+\n     ${NS}::checkbutton $page.autoselect -text [mc \"Auto-select SHA1\n(length)\"] \\\n  -variable autoselect\n     spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen\n     grid x $page.autoselect $page.autosellen -sticky w\n+\n     ${NS}::checkbutton $page.hideremotes -text [mc \"Hide remote refs\"] \\\n  -variable hideremotes\n     grid x $page.hideremotes -sticky w\n+    if { $have_inotify } {\n+        ${NS}::checkbutton $page.autoupdate -text [mc \"Auto-update\nupon change (ms)\"] \\\n+            -variable autoupdate\n+        spinbox $page.autoupdatedebounce -from 10 -to 60000 -width 7\n-textvariable autoupdatedebounce\n+        grid x $page.autoupdate $page.autoupdatedebounce -sticky w\n+    }\n\n     ${NS}::label $page.ddisp -text [mc \"Diff display options\"]\n     grid $page.ddisp - -sticky w -pady 10\n@@ -11765,7 +11780,8 @@ proc prefsok {} {\n     global oldprefs prefstop showneartags showlocalchanges\n     global fontpref mainfont textfont uifont\n     global limitdiffs treediffs perfile_attrs\n-    global hideremotes\n+    global hideremotes autoupdate\n+    global gitdir\n\n     catch {destroy $prefstop}\n     unset prefstop\n@@ -11814,6 +11830,8 @@ proc prefsok {} {\n     if {$hideremotes != $oldprefs(hideremotes)} {\n  rereadrefs\n     }\n+\n+    handle_inotify $gitdir true\n }\n\n proc formatdate {d} {\n@@ -12295,6 +12313,13 @@ set autoselect 1\n set autosellen 40\n set perfile_attrs 0\n set want_ttk 1\n+set autoupdate 1\n+set autoupdatedebounce 100\n+#timer id for inotify reloading\n+set reload_id -1\n+#timer id for inotify updating (less than reload)\n+set update_id -1\n+set inotify_instance -1\n\n if {[tk windowingsystem] eq \"aqua\"} {\n     set extdifftool \"opendiff\"\n@@ -12390,6 +12415,7 @@ set config_variables {\n     filesepbgcolor filesepfgcolor linehoverbgcolor linehoverfgcolor\n     linehoveroutlinecolor mainheadcirclecolor workingfilescirclecolor\n     indexcirclecolor circlecolors linkfgcolor circleoutlinecolor\n+    autoupdate autoupdatedebounce\n }\n foreach var $config_variables {\n     config_init_trace $var\n@@ -12477,6 +12503,149 @@ if {$i >= [llength $argv] && $revtreeargs ne {}} {\n     }\n }\n\n+#function to be called after inotify reload-timeout\n+proc reload_helper {} {\n+    #puts \"RELOAD\"\n+    global reload_id\n+    set reload_id -1\n+    reloadcommits\n+    set head [exec git rev-parse HEAD]\n+    selbyid $head\n+}\n+\n+#function to be called after inotify update-timeout\n+proc update_helper {} {\n+    #puts \"UPDATE\"\n+    global update_id\n+    set update_id -1\n+    updatecommits\n+    set head [exec git rev-parse HEAD]\n+    selbyid $head\n+}\n+\n+proc inotify_handler { fd } {\n+    global autoupdate reload_id update_id autoupdatedebounce\n+    set events [inotify_watch read]\n+    set watch_info [inotify_watch info]\n+    set update_view false\n+    set reloadcommits false\n+\n+    #cancel pending timer\n+    if { $reload_id ne -1 } {\n+        #puts \"cancel a reload\"\n+        after cancel $reload_id\n+        set reload_id -1\n+        set update_view true\n+        set reloadcommits true\n+    }\n+\n+    if { $update_id ne -1 } {\n+        #puts \"cancel an update\"\n+        after cancel $update_id\n+        set update_id -1\n+        set update_view true\n+    }\n+\n+    foreach {event} $events {\n+        set current_watchid [dict get $event watchid]\n+        set flags [dict get $event flags]\n+        set event_filename [dict get $event filename]\n+\n+        foreach {path watchid watch_flags} $watch_info {\n+            if {$watchid eq $current_watchid} {\n+                set watch_path $path\n+            }\n+        }\n+\n+        set full_filename [file join $watch_path $event_filename]\n+        #check wether we should do update or reload below\n+        #puts \"Got: $full_filename / $event_filename ($flags)\"\n+\n+        if {$flags eq \"nD\"} {\n+            inotify_watch add $full_filename \"nwds\"\n+        }\n+        if {![string match *.lock $event_filename]} {\n+            if { $flags eq \"d\" } {\n+                #stuff like deleting branches should result in reloading\n+                set reloadcommits true\n+            }\n+            set update_view true\n+        }\n+\n+        #simple commit just needs updating right?\n+        #if { $event_filename eq \"COMMIT_EDITMSG\" } {\n+        #    set reloadcommits true\n+        #}\n+    }\n+\n+    #reloadcommits or updatecommits - depending on file and operation?\n+    if { $update_view } {\n+        if { $reloadcommits } {\n+            #puts \"schedule reload\"\n+            set reload_id [after $autoupdatedebounce reload_helper]\n+        } else {\n+            #puts \"schedule update\"\n+            set update_id [after $autoupdatedebounce update_helper]\n+        }\n+    }\n+}\n+\n+proc watch_recursive { dir } {\n+    inotify_watch add $dir \"nwaCmMds\"\n+\n+    foreach i [glob -nocomplain -dir $dir *] {\n+        if {[file type $i] eq {directory}} {\n+            watch_recursive $i\n+        }\n+    }\n+}\n+\n+proc enable_inotify { dir redraw} {\n+    global inotify_instance autoupdatedebounce reload_id\n+\n+    if { $inotify_instance ne -1 } {\n+        updatecommits\n+    } else {\n+        set inotify_instance [inotify create \"inotify_watch\"\n\"::inotify_handler\"]\n+        watch_recursive $dir\n+        if { $redraw } {\n+            set reload_id [after $autoupdatedebounce reload_helper]\n+        }\n+    }\n+}\n+\n+proc disable_inotify {} {\n+    global inotify_instance reload_id update_id\n+\n+    if { $inotify_instance ne -1 } {\n+        rename inotify_watch {}\n+        set inotify_instance -1\n+    }\n+\n+    if { $reload_id ne -1 } {\n+        after cancel $reload_id\n+        set reload_id -1\n+    }\n+\n+    if { $update_id ne -1 } {\n+        after cancel $update_id\n+        set update_id -1\n+    }\n+}\n+\n+proc handle_inotify { dir redraw } {\n+    global have_inotify autoupdate\n+    if { $have_inotify } {\n+        if { $autoupdate } {\n+            enable_inotify $dir $redraw\n+        } else {\n+            disable_inotify\n+        }\n+    }\n+}\n+\n+handle_inotify $gitdir false\n+\n set nullid \"0000000000000000000000000000000000000000\"\n set nullid2 \"0000000000000000000000000000000000000001\"\n set nullfile \"/dev/null\"\n-- \n2.7.4\n"}]}