parent
d3b60cc445
commit
21eb37e471
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/d5/tengo/v2"
|
||||
"github.com/d5/tengo/v2/stdlib"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/matterbridge/emoji"
|
||||
"github.com/kyokomi/emoji/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -127,7 +127,7 @@ func (gw *Gateway) AddConfig(cfg *config.Gateway) error {
|
|||
gw.logger.Errorf("mapChannels() failed: %s", err)
|
||||
}
|
||||
for _, br := range append(gw.MyConfig.In, append(gw.MyConfig.InOut, gw.MyConfig.Out...)...) {
|
||||
br := br //scopelint
|
||||
br := br // scopelint
|
||||
err := gw.AddBridge(&br)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -386,6 +386,7 @@ func (gw *Gateway) modifyMessage(msg *config.Message) {
|
|||
}
|
||||
|
||||
// replace :emoji: to unicode
|
||||
emoji.ReplacePadding = ""
|
||||
msg.Text = emoji.Sprint(msg.Text)
|
||||
|
||||
br := gw.Bridges[msg.Account]
|
||||
|
@ -496,7 +497,7 @@ func (gw *Gateway) SendMessage(
|
|||
if mID != "" {
|
||||
gw.logger.Debugf("mID %s: %s", dest.Account, mID)
|
||||
return mID, nil
|
||||
//brMsgIDs = append(brMsgIDs, &BrMsgID{dest, dest.Protocol + " " + mID, channel.ID})
|
||||
// brMsgIDs = append(brMsgIDs, &BrMsgID{dest, dest.Protocol + " " + mID, channel.ID})
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
|
17
go.mod
17
go.mod
|
@ -3,9 +3,9 @@ module github.com/42wim/matterbridge
|
|||
require (
|
||||
github.com/42wim/go-gitter v0.0.0-20170828205020-017310c2d557
|
||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||
github.com/Jeffail/gabs v1.4.0 // indirect
|
||||
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
||||
github.com/Rhymen/go-whatsapp v0.1.2-0.20210126174449-3c094ebae0ce
|
||||
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210112200207-10ab4d695d60 // indirect
|
||||
github.com/SevereCloud/vksdk/v2 v2.9.0
|
||||
github.com/d5/tengo/v2 v2.7.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
|
@ -13,17 +13,18 @@ require (
|
|||
github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81
|
||||
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8
|
||||
github.com/google/gops v0.3.17
|
||||
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/golang-lru v0.5.4
|
||||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20200505163032-5cacf52379da
|
||||
github.com/kyokomi/emoji/v2 v2.2.8
|
||||
github.com/labstack/echo/v4 v4.2.1
|
||||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7
|
||||
github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20201206215757-c1d86d75b9f8
|
||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d
|
||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050
|
||||
github.com/matterbridge/gozulipbot v0.0.0-20200820220548-be5824faa913
|
||||
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
||||
|
@ -35,11 +36,11 @@ require (
|
|||
github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect
|
||||
github.com/nelsonken/gomf v0.0.0-20180504123937-a9dd2f9deae9
|
||||
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
||||
github.com/rs/xid v1.2.1
|
||||
github.com/rs/xid v1.3.0
|
||||
github.com/russross/blackfriday v1.6.0
|
||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
|
||||
github.com/shazow/ssh-chat v1.10.1
|
||||
github.com/sirupsen/logrus v1.8.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/slack-go/slack v0.8.2
|
||||
github.com/spf13/afero v1.3.4 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
|
@ -49,9 +50,9 @@ require (
|
|||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||
github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect
|
||||
github.com/yaegashi/msgraph.go v0.1.4
|
||||
github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2
|
||||
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
gomod.garykim.dev/nc-talk v0.1.7
|
||||
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
|
||||
layeh.com/gumble v0.0.0-20200818122324-146f9205029b
|
||||
|
|
34
go.sum
34
go.sum
|
@ -85,8 +85,6 @@ github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf
|
|||
github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:suwzklatySS3Q0+NCxCDh5hYfgXdQUWU1DNcxwAxStM=
|
||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/RoaringBitmap/roaring v0.5.1/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210112200207-10ab4d695d60 h1:prBTRx78AQnXzivNT9Crhu564W/zPPr3ibSlpT9xKcE=
|
||||
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210112200207-10ab4d695d60/go.mod h1:rjP7sIipbZcagro/6TCk6X0ZeFT2eyudH5+fve/cbBA=
|
||||
github.com/SevereCloud/vksdk/v2 v2.9.0 h1:39qjzmozK5FDfnDkfA+YN0CtKi4mDrzjPtoT5GN9Xg0=
|
||||
github.com/SevereCloud/vksdk/v2 v2.9.0/go.mod h1:IBmfJ3rs+zDLD9NHCoJEpgg5A4UOoxgUU/g8p5lYb48=
|
||||
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
|
||||
|
@ -195,7 +193,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchote/go-openal v0.0.0-20171116030048-f4a9a141d372/go.mod h1:74z+CYu2/mx4N+mcIS/rsvfAxBPBV9uv8zRAnwyFkdI=
|
||||
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
|
@ -509,6 +506,8 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
|
||||
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
|
||||
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||
github.com/labstack/echo/v4 v4.2.1 h1:LF5Iq7t/jrtUuSutNuiEWtB5eiHfZ5gSe2pcu5exjQw=
|
||||
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||
|
@ -527,22 +526,18 @@ github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 h1:BS9tqL0OCiOGuy/C
|
|||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7/go.mod h1:liX5MxHPrwgHaKowoLkYGwbXfYABh1jbZ6FpElbGF1I=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
|
||||
github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd h1:xVrqJK3xHREMNjwjljkAUaadalWc0rRbmVuQatzmgwg=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20201206215757-c1d86d75b9f8 h1:2iHni9FGPRRnaZrknLp+Kyr1CWbRIRUjp89TNpkqy3I=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20201206215757-c1d86d75b9f8/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4=
|
||||
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d h1:Csy27nDj00vRGp2+QvwSanaW0RA60SZUHXCk4BBT0AU=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7 h1:4J2YZuY8dIYrxbLMsWGqPZb/B59ygCwSBkyZHez5PSY=
|
||||
github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7/go.mod h1:411nZYv0UMMrtppR5glXop1foboJiFAowy+42U+Ahvw=
|
||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible h1:oaOqwbg5HxHRxvAbd84ks0Okwoc1ISyUZ87EiVJFhGI=
|
||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible/go.mod h1:igE6rUAn3jai2wCdsjFHfhUoekjrFthoEjFObKKwSb4=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050 h1:kWkP1lXpkvtoNL08jkP3XQH/zvDOEXJpdCJd/DlIvMw=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||
github.com/matterbridge/gozulipbot v0.0.0-20200820220548-be5824faa913 h1:5UGr9fLsvAvhjP6i5XJmd0ZIwYVR2gZCzU1lJZ7wfLY=
|
||||
|
@ -763,8 +758,9 @@ github.com/rickb777/plural v1.2.0/go.mod h1:UdpyWFCGbo3mvK3f/PfZOAOrkjzJlYN/sD46
|
|||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rudderlabs/analytics-go v3.2.1+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30=
|
||||
github.com/russellhaering/goxmldsig v1.1.0/go.mod h1:QK8GhXPB3+AfuCrfo0oRISa9NfzeCpWmxeGnqEpDF9o=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
|
@ -816,8 +812,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
|||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.0 h1:nfhvjKcUMhBMVqbKHJlk5RPrrfYr/NMo3692g0dwfWU=
|
||||
github.com/sirupsen/logrus v1.8.0/go.mod h1:4GuYW9TZmE769R5STWrRakJc4UqQ3+QQ95fyz7ENv1A=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
|
||||
github.com/slack-go/slack v0.8.2 h1:D7jNu0AInBfdQ4QyKPtVSp+ZxQes3EzWW17RZ/va4JE=
|
||||
|
@ -830,7 +826,6 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
|
|||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
|
@ -945,8 +940,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2 h1:UQwvu7FjUEdVYofx0U6bsc5odNE7wa5TSA0fl559GcA=
|
||||
github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2/go.mod h1:0MsIttMJIF/8Y7x0XjonJP7K99t3sR6bjj4m5S4JmqU=
|
||||
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134 h1:itYC8Ycx8aVBN7a8q1Yr187W5WmQthvYU13+f4rOWkU=
|
||||
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134/go.mod h1:0MsIttMJIF/8Y7x0XjonJP7K99t3sR6bjj4m5S4JmqU=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
|
@ -1089,7 +1084,6 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/
|
|||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0 h1:wBouT66WTYFXdxfVdz9sVWARVd/2vfGcmI45D2gj45M=
|
||||
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
|
@ -1100,8 +1094,8 @@ golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4Iltr
|
|||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84 h1:duBc5zuJsmJXYOVVE/6PxejI+N3AaCqKjtsoLn1Je5Q=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc=
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
|
@ -3,19 +3,19 @@ Emoji is a simple golang package.
|
|||
|
||||
[![wercker status](https://app.wercker.com/status/7bef60de2c6d3e0e6c13d56b2393c5d8/s/master "wercker status")](https://app.wercker.com/project/byKey/7bef60de2c6d3e0e6c13d56b2393c5d8)
|
||||
[![Coverage Status](https://coveralls.io/repos/kyokomi/emoji/badge.png?branch=master)](https://coveralls.io/r/kyokomi/emoji?branch=master)
|
||||
[![GoDoc](https://godoc.org/github.com/kyokomi/emoji?status.svg)](https://godoc.org/github.com/kyokomi/emoji)
|
||||
[![GoDoc](https://pkg.go.dev/badge/github.com/kyokomi/emoji.svg)](https://pkg.go.dev/github.com/kyokomi/emoji/v2)
|
||||
|
||||
Get it:
|
||||
|
||||
```
|
||||
go get github.com/kyokomi/emoji
|
||||
go get github.com/kyokomi/emoji/v2
|
||||
```
|
||||
|
||||
Import it:
|
||||
|
||||
```
|
||||
import (
|
||||
"github.com/kyokomi/emoji"
|
||||
"github.com/kyokomi/emoji/v2"
|
||||
)
|
||||
```
|
||||
|
||||
|
@ -27,7 +27,7 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kyokomi/emoji"
|
||||
"github.com/kyokomi/emoji/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -46,7 +46,7 @@ func main() {
|
|||
|
||||
## Reference
|
||||
|
||||
- [GitHub EMOJI CHEAT SHEET](http://www.emoji-cheat-sheet.com/)
|
||||
- [unicode Emoji Charts](http://www.unicode.org/emoji/charts/emoji-list.html)
|
||||
|
||||
## License
|
||||
|
|
@ -10,23 +10,47 @@ import (
|
|||
"unicode"
|
||||
)
|
||||
|
||||
//go:generate generateEmojiCodeMap -pkg emoji
|
||||
//go:generate generateEmojiCodeMap -pkg emoji -o emoji_codemap.go
|
||||
|
||||
// Replace Padding character for emoji.
|
||||
const (
|
||||
ReplacePadding = ""
|
||||
var (
|
||||
ReplacePadding = " "
|
||||
)
|
||||
|
||||
// CodeMap gets the underlying map of emoji.
|
||||
func CodeMap() map[string]string {
|
||||
return emojiCodeMap
|
||||
return emojiCode()
|
||||
}
|
||||
|
||||
// RevCodeMap gets the underlying map of emoji.
|
||||
func RevCodeMap() map[string][]string {
|
||||
return emojiRevCode()
|
||||
}
|
||||
|
||||
func AliasList(shortCode string) []string {
|
||||
return emojiRevCode()[emojiCode()[shortCode]]
|
||||
}
|
||||
|
||||
// HasAlias flags if the given `shortCode` has multiple aliases with other
|
||||
// codes.
|
||||
func HasAlias(shortCode string) bool {
|
||||
return len(AliasList(shortCode)) > 1
|
||||
}
|
||||
|
||||
// NormalizeShortCode normalizes a given `shortCode` to a deterministic alias.
|
||||
func NormalizeShortCode(shortCode string) string {
|
||||
shortLists := AliasList(shortCode)
|
||||
if len(shortLists) == 0 {
|
||||
return shortCode
|
||||
}
|
||||
return shortLists[0]
|
||||
}
|
||||
|
||||
// regular expression that matches :flag-[countrycode]:
|
||||
var flagRegexp = regexp.MustCompile(":flag-([a-z]{2}):")
|
||||
|
||||
func emojize(x string) string {
|
||||
str, ok := emojiCodeMap[x]
|
||||
str, ok := emojiCode()[x]
|
||||
if ok {
|
||||
return str + ReplacePadding
|
||||
}
|
||||
|
@ -99,7 +123,7 @@ func Println(a ...interface{}) (int, error) {
|
|||
|
||||
// Printf is fmt.Printf which supports emoji
|
||||
func Printf(format string, a ...interface{}) (int, error) {
|
||||
return fmt.Printf(compile(fmt.Sprintf(format, a...)))
|
||||
return fmt.Print(compile(fmt.Sprintf(format, a...)))
|
||||
}
|
||||
|
||||
// Fprint is fmt.Fprint which supports emoji
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
|||
module github.com/kyokomi/emoji/v2
|
||||
|
||||
go 1.14
|
|
@ -3,9 +3,13 @@ build:
|
|||
steps:
|
||||
- setup-go-workspace
|
||||
- script:
|
||||
name: install goveralls
|
||||
name: go version
|
||||
code: go version
|
||||
- script:
|
||||
name: install tools
|
||||
code: |
|
||||
go get github.com/mattn/goveralls
|
||||
GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
- script:
|
||||
name: go get
|
||||
code: |
|
||||
|
@ -14,6 +18,10 @@ build:
|
|||
name: go build
|
||||
code: |
|
||||
go build ./...
|
||||
- script:
|
||||
name: golangci-lint
|
||||
code: |
|
||||
golangci-lint run
|
||||
- script:
|
||||
name: go test
|
||||
code: |
|
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2017 the Mage authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,80 +0,0 @@
|
|||
package mg
|
||||
|
||||
// Color is ANSI color type
|
||||
type Color int
|
||||
|
||||
// If you add/change/remove any items in this constant,
|
||||
// you will need to run "stringer -type=Color" in this directory again.
|
||||
// NOTE: Please keep the list in an alphabetical order.
|
||||
const (
|
||||
Black Color = iota
|
||||
Red
|
||||
Green
|
||||
Yellow
|
||||
Blue
|
||||
Magenta
|
||||
Cyan
|
||||
White
|
||||
BrightBlack
|
||||
BrightRed
|
||||
BrightGreen
|
||||
BrightYellow
|
||||
BrightBlue
|
||||
BrightMagenta
|
||||
BrightCyan
|
||||
BrightWhite
|
||||
)
|
||||
|
||||
// AnsiColor are ANSI color codes for supported terminal colors.
|
||||
var ansiColor = map[Color]string{
|
||||
Black: "\u001b[30m",
|
||||
Red: "\u001b[31m",
|
||||
Green: "\u001b[32m",
|
||||
Yellow: "\u001b[33m",
|
||||
Blue: "\u001b[34m",
|
||||
Magenta: "\u001b[35m",
|
||||
Cyan: "\u001b[36m",
|
||||
White: "\u001b[37m",
|
||||
BrightBlack: "\u001b[30;1m",
|
||||
BrightRed: "\u001b[31;1m",
|
||||
BrightGreen: "\u001b[32;1m",
|
||||
BrightYellow: "\u001b[33;1m",
|
||||
BrightBlue: "\u001b[34;1m",
|
||||
BrightMagenta: "\u001b[35;1m",
|
||||
BrightCyan: "\u001b[36;1m",
|
||||
BrightWhite: "\u001b[37;1m",
|
||||
}
|
||||
|
||||
// AnsiColorReset is an ANSI color code to reset the terminal color.
|
||||
const AnsiColorReset = "\033[0m"
|
||||
|
||||
// DefaultTargetAnsiColor is a default ANSI color for colorizing targets.
|
||||
// It is set to Cyan as an arbitrary color, because it has a neutral meaning
|
||||
var DefaultTargetAnsiColor = ansiColor[Cyan]
|
||||
|
||||
func toLowerCase(s string) string {
|
||||
// this is a naive implementation
|
||||
// borrowed from https://golang.org/src/strings/strings.go
|
||||
// and only considers alphabetical characters [a-zA-Z]
|
||||
// so that we don't depend on the "strings" package
|
||||
buf := make([]byte, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
c += 'a' - 'A'
|
||||
}
|
||||
buf[i] = c
|
||||
}
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func getAnsiColor(color string) (string, bool) {
|
||||
colorLower := toLowerCase(color)
|
||||
for k, v := range ansiColor {
|
||||
colorConstLower := toLowerCase(k.String())
|
||||
if colorConstLower == colorLower {
|
||||
return v, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// Code generated by "stringer -type=Color"; DO NOT EDIT.
|
||||
|
||||
package mg
|
||||
|
||||
import "strconv"
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[Black-0]
|
||||
_ = x[Red-1]
|
||||
_ = x[Green-2]
|
||||
_ = x[Yellow-3]
|
||||
_ = x[Blue-4]
|
||||
_ = x[Magenta-5]
|
||||
_ = x[Cyan-6]
|
||||
_ = x[White-7]
|
||||
_ = x[BrightBlack-8]
|
||||
_ = x[BrightRed-9]
|
||||
_ = x[BrightGreen-10]
|
||||
_ = x[BrightYellow-11]
|
||||
_ = x[BrightBlue-12]
|
||||
_ = x[BrightMagenta-13]
|
||||
_ = x[BrightCyan-14]
|
||||
_ = x[BrightWhite-15]
|
||||
}
|
||||
|
||||
const _Color_name = "BlackRedGreenYellowBlueMagentaCyanWhiteBrightBlackBrightRedBrightGreenBrightYellowBrightBlueBrightMagentaBrightCyanBrightWhite"
|
||||
|
||||
var _Color_index = [...]uint8{0, 5, 8, 13, 19, 23, 30, 34, 39, 50, 59, 70, 82, 92, 105, 115, 126}
|
||||
|
||||
func (i Color) String() string {
|
||||
if i < 0 || i >= Color(len(_Color_index)-1) {
|
||||
return "Color(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _Color_name[_Color_index[i]:_Color_index[i+1]]
|
||||
}
|
|
@ -1,352 +0,0 @@
|
|||
package mg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// funcType indicates a prototype of build job function
|
||||
type funcType int
|
||||
|
||||
// funcTypes
|
||||
const (
|
||||
invalidType funcType = iota
|
||||
voidType
|
||||
errorType
|
||||
contextVoidType
|
||||
contextErrorType
|
||||
namespaceVoidType
|
||||
namespaceErrorType
|
||||
namespaceContextVoidType
|
||||
namespaceContextErrorType
|
||||
)
|
||||
|
||||
var logger = log.New(os.Stderr, "", 0)
|
||||
|
||||
type onceMap struct {
|
||||
mu *sync.Mutex
|
||||
m map[string]*onceFun
|
||||
}
|
||||
|
||||
func (o *onceMap) LoadOrStore(s string, one *onceFun) *onceFun {
|
||||
defer o.mu.Unlock()
|
||||
o.mu.Lock()
|
||||
|
||||
existing, ok := o.m[s]
|
||||
if ok {
|
||||
return existing
|
||||
}
|
||||
o.m[s] = one
|
||||
return one
|
||||
}
|
||||
|
||||
var onces = &onceMap{
|
||||
mu: &sync.Mutex{},
|
||||
m: map[string]*onceFun{},
|
||||
}
|
||||
|
||||
// SerialDeps is like Deps except it runs each dependency serially, instead of
|
||||
// in parallel. This can be useful for resource intensive dependencies that
|
||||
// shouldn't be run at the same time.
|
||||
func SerialDeps(fns ...interface{}) {
|
||||
types := checkFns(fns)
|
||||
ctx := context.Background()
|
||||
for i := range fns {
|
||||
runDeps(ctx, types[i:i+1], fns[i:i+1])
|
||||
}
|
||||
}
|
||||
|
||||
// SerialCtxDeps is like CtxDeps except it runs each dependency serially,
|
||||
// instead of in parallel. This can be useful for resource intensive
|
||||
// dependencies that shouldn't be run at the same time.
|
||||
func SerialCtxDeps(ctx context.Context, fns ...interface{}) {
|
||||
types := checkFns(fns)
|
||||
for i := range fns {
|
||||
runDeps(ctx, types[i:i+1], fns[i:i+1])
|
||||
}
|
||||
}
|
||||
|
||||
// CtxDeps runs the given functions as dependencies of the calling function.
|
||||
// Dependencies must only be of type:
|
||||
// func()
|
||||
// func() error
|
||||
// func(context.Context)
|
||||
// func(context.Context) error
|
||||
// Or a similar method on a mg.Namespace type.
|
||||
//
|
||||
// The function calling Deps is guaranteed that all dependent functions will be
|
||||
// run exactly once when Deps returns. Dependent functions may in turn declare
|
||||
// their own dependencies using Deps. Each dependency is run in their own
|
||||
// goroutines. Each function is given the context provided if the function
|
||||
// prototype allows for it.
|
||||
func CtxDeps(ctx context.Context, fns ...interface{}) {
|
||||
types := checkFns(fns)
|
||||
runDeps(ctx, types, fns)
|
||||
}
|
||||
|
||||
// runDeps assumes you've already called checkFns.
|
||||
func runDeps(ctx context.Context, types []funcType, fns []interface{}) {
|
||||
mu := &sync.Mutex{}
|
||||
var errs []string
|
||||
var exit int
|
||||
wg := &sync.WaitGroup{}
|
||||
for i, f := range fns {
|
||||
fn := addDep(ctx, types[i], f)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer func() {
|
||||
if v := recover(); v != nil {
|
||||
mu.Lock()
|
||||
if err, ok := v.(error); ok {
|
||||
exit = changeExit(exit, ExitStatus(err))
|
||||
} else {
|
||||
exit = changeExit(exit, 1)
|
||||
}
|
||||
errs = append(errs, fmt.Sprint(v))
|
||||
mu.Unlock()
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
if err := fn.run(); err != nil {
|
||||
mu.Lock()
|
||||
errs = append(errs, fmt.Sprint(err))
|
||||
exit = changeExit(exit, ExitStatus(err))
|
||||
mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
if len(errs) > 0 {
|
||||
panic(Fatal(exit, strings.Join(errs, "\n")))
|
||||
}
|
||||
}
|
||||
|
||||
func checkFns(fns []interface{}) []funcType {
|
||||
types := make([]funcType, len(fns))
|
||||
for i, f := range fns {
|
||||
t, err := funcCheck(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
types[i] = t
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
// Deps runs the given functions in parallel, exactly once. Dependencies must
|
||||
// only be of type:
|
||||
// func()
|
||||
// func() error
|
||||
// func(context.Context)
|
||||
// func(context.Context) error
|
||||
// Or a similar method on a mg.Namespace type.
|
||||
//
|
||||
// This is a way to build up a tree of dependencies with each dependency
|
||||
// defining its own dependencies. Functions must have the same signature as a
|
||||
// Mage target, i.e. optional context argument, optional error return.
|
||||
func Deps(fns ...interface{}) {
|
||||
CtxDeps(context.Background(), fns...)
|
||||
}
|
||||
|
||||
func changeExit(old, new int) int {
|
||||
if new == 0 {
|
||||
return old
|
||||
}
|
||||
if old == 0 {
|
||||
return new
|
||||
}
|
||||
if old == new {
|
||||
return old
|
||||
}
|
||||
// both different and both non-zero, just set
|
||||
// exit to 1. Nothing more we can do.
|
||||
return 1
|
||||
}
|
||||
|
||||
func addDep(ctx context.Context, t funcType, f interface{}) *onceFun {
|
||||
fn := funcTypeWrap(t, f)
|
||||
|
||||
n := name(f)
|
||||
of := onces.LoadOrStore(n, &onceFun{
|
||||
fn: fn,
|
||||
ctx: ctx,
|
||||
|
||||
displayName: displayName(n),
|
||||
})
|
||||
return of
|
||||
}
|
||||
|
||||
func name(i interface{}) string {
|
||||
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||
}
|
||||
|
||||
func displayName(name string) string {
|
||||
splitByPackage := strings.Split(name, ".")
|
||||
if len(splitByPackage) == 2 && splitByPackage[0] == "main" {
|
||||
return splitByPackage[len(splitByPackage)-1]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
type onceFun struct {
|
||||
once sync.Once
|
||||
fn func(context.Context) error
|
||||
ctx context.Context
|
||||
err error
|
||||
|
||||
displayName string
|
||||
}
|
||||
|
||||
func (o *onceFun) run() error {
|
||||
o.once.Do(func() {
|
||||
if Verbose() {
|
||||
logger.Println("Running dependency:", o.displayName)
|
||||
}
|
||||
o.err = o.fn(o.ctx)
|
||||
})
|
||||
return o.err
|
||||
}
|
||||
|
||||
// Returns a location of mg.Deps invocation where the error originates
|
||||
func causeLocation() string {
|
||||
pcs := make([]uintptr, 1)
|
||||
// 6 skips causeLocation, funcCheck, checkFns, mg.CtxDeps, mg.Deps in stacktrace
|
||||
if runtime.Callers(6, pcs) != 1 {
|
||||
return "<unknown>"
|
||||
}
|
||||
frames := runtime.CallersFrames(pcs)
|
||||
frame, _ := frames.Next()
|
||||
if frame.Function == "" && frame.File == "" && frame.Line == 0 {
|
||||
return "<unknown>"
|
||||
}
|
||||
return fmt.Sprintf("%s %s:%d", frame.Function, frame.File, frame.Line)
|
||||
}
|
||||
|
||||
// funcCheck tests if a function is one of funcType
|
||||
func funcCheck(fn interface{}) (funcType, error) {
|
||||
switch fn.(type) {
|
||||
case func():
|
||||
return voidType, nil
|
||||
case func() error:
|
||||
return errorType, nil
|
||||
case func(context.Context):
|
||||
return contextVoidType, nil
|
||||
case func(context.Context) error:
|
||||
return contextErrorType, nil
|
||||
}
|
||||
|
||||
err := fmt.Errorf("Invalid type for dependent function: %T. Dependencies must be func(), func() error, func(context.Context), func(context.Context) error, or the same method on an mg.Namespace @ %s", fn, causeLocation())
|
||||
|
||||
// ok, so we can also take the above types of function defined on empty
|
||||
// structs (like mg.Namespace). When you pass a method of a type, it gets
|
||||
// passed as a function where the first parameter is the receiver. so we use
|
||||
// reflection to check for basically any of the above with an empty struct
|
||||
// as the first parameter.
|
||||
|
||||
t := reflect.TypeOf(fn)
|
||||
if t.Kind() != reflect.Func {
|
||||
return invalidType, err
|
||||
}
|
||||
|
||||
if t.NumOut() > 1 {
|
||||
return invalidType, err
|
||||
}
|
||||
if t.NumOut() == 1 && t.Out(0) == reflect.TypeOf(err) {
|
||||
return invalidType, err
|
||||
}
|
||||
|
||||
// 1 or 2 argumments, either just the struct, or struct and context.
|
||||
if t.NumIn() == 0 || t.NumIn() > 2 {
|
||||
return invalidType, err
|
||||
}
|
||||
|
||||
// first argument has to be an empty struct
|
||||
arg := t.In(0)
|
||||
if arg.Kind() != reflect.Struct {
|
||||
return invalidType, err
|
||||
}
|
||||
if arg.NumField() != 0 {
|
||||
return invalidType, err
|
||||
}
|
||||
if t.NumIn() == 1 {
|
||||
if t.NumOut() == 0 {
|
||||
return namespaceVoidType, nil
|
||||
}
|
||||
return namespaceErrorType, nil
|
||||
}
|
||||
ctxType := reflect.TypeOf(context.Background())
|
||||
if t.In(1) == ctxType {
|
||||
return invalidType, err
|
||||
}
|
||||
|
||||
if t.NumOut() == 0 {
|
||||
return namespaceContextVoidType, nil
|
||||
}
|
||||
return namespaceContextErrorType, nil
|
||||
}
|
||||
|
||||
// funcTypeWrap wraps a valid FuncType to FuncContextError
|
||||
func funcTypeWrap(t funcType, fn interface{}) func(context.Context) error {
|
||||
switch f := fn.(type) {
|
||||
case func():
|
||||
return func(context.Context) error {
|
||||
f()
|
||||
return nil
|
||||
}
|
||||
case func() error:
|
||||
return func(context.Context) error {
|
||||
return f()
|
||||
}
|
||||
case func(context.Context):
|
||||
return func(ctx context.Context) error {
|
||||
f(ctx)
|
||||
return nil
|
||||
}
|
||||
case func(context.Context) error:
|
||||
return f
|
||||
}
|
||||
args := []reflect.Value{reflect.ValueOf(struct{}{})}
|
||||
switch t {
|
||||
case namespaceVoidType:
|
||||
return func(context.Context) error {
|
||||
v := reflect.ValueOf(fn)
|
||||
v.Call(args)
|
||||
return nil
|
||||
}
|
||||
case namespaceErrorType:
|
||||
return func(context.Context) error {
|
||||
v := reflect.ValueOf(fn)
|
||||
ret := v.Call(args)
|
||||
val := ret[0].Interface()
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
return val.(error)
|
||||
}
|
||||
case namespaceContextVoidType:
|
||||
return func(ctx context.Context) error {
|
||||
v := reflect.ValueOf(fn)
|
||||
v.Call(append(args, reflect.ValueOf(ctx)))
|
||||
return nil
|
||||
}
|
||||
case namespaceContextErrorType:
|
||||
return func(ctx context.Context) error {
|
||||
v := reflect.ValueOf(fn)
|
||||
ret := v.Call(append(args, reflect.ValueOf(ctx)))
|
||||
val := ret[0].Interface()
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
return val.(error)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("Don't know how to deal with dep of type %T", fn))
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package mg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type fatalErr struct {
|
||||
code int
|
||||
error
|
||||
}
|
||||
|
||||
func (f fatalErr) ExitStatus() int {
|
||||
return f.code
|
||||
}
|
||||
|
||||
type exitStatus interface {
|
||||
ExitStatus() int
|
||||
}
|
||||
|
||||
// Fatal returns an error that will cause mage to print out the
|
||||
// given args and exit with the given exit code.
|
||||
func Fatal(code int, args ...interface{}) error {
|
||||
return fatalErr{
|
||||
code: code,
|
||||
error: errors.New(fmt.Sprint(args...)),
|
||||
}
|
||||
}
|
||||
|
||||
// Fatalf returns an error that will cause mage to print out the
|
||||
// given message and exit with the given exit code.
|
||||
func Fatalf(code int, format string, args ...interface{}) error {
|
||||
return fatalErr{
|
||||
code: code,
|
||||
error: fmt.Errorf(format, args...),
|
||||
}
|
||||
}
|
||||
|
||||
// ExitStatus queries the error for an exit status. If the error is nil, it
|
||||
// returns 0. If the error does not implement ExitStatus() int, it returns 1.
|
||||
// Otherwise it retiurns the value from ExitStatus().
|
||||
func ExitStatus(err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
exit, ok := err.(exitStatus)
|
||||
if !ok {
|
||||
return 1
|
||||
}
|
||||
return exit.ExitStatus()
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
package mg
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// CacheEnv is the environment variable that users may set to change the
|
||||
// location where mage stores its compiled binaries.
|
||||
const CacheEnv = "MAGEFILE_CACHE"
|
||||
|
||||
// VerboseEnv is the environment variable that indicates the user requested
|
||||
// verbose mode when running a magefile.
|
||||
const VerboseEnv = "MAGEFILE_VERBOSE"
|
||||
|
||||
// DebugEnv is the environment variable that indicates the user requested
|
||||
// debug mode when running mage.
|
||||
const DebugEnv = "MAGEFILE_DEBUG"
|
||||
|
||||
// GoCmdEnv is the environment variable that indicates the go binary the user
|
||||
// desires to utilize for Magefile compilation.
|
||||
const GoCmdEnv = "MAGEFILE_GOCMD"
|
||||
|
||||
// IgnoreDefaultEnv is the environment variable that indicates the user requested
|
||||
// to ignore the default target specified in the magefile.
|
||||
const IgnoreDefaultEnv = "MAGEFILE_IGNOREDEFAULT"
|
||||
|
||||
// HashFastEnv is the environment variable that indicates the user requested to
|
||||
// use a quick hash of magefiles to determine whether or not the magefile binary
|
||||
// needs to be rebuilt. This results in faster runtimes, but means that mage
|
||||
// will fail to rebuild if a dependency has changed. To force a rebuild, run
|
||||
// mage with the -f flag.
|
||||
const HashFastEnv = "MAGEFILE_HASHFAST"
|
||||
|
||||
// EnableColorEnv is the environment variable that indicates the user is using
|
||||
// a terminal which supports a color output. The default is false for backwards
|
||||
// compatibility. When the value is true and the detected terminal does support colors
|
||||
// then the list of mage targets will be displayed in ANSI color. When the value
|
||||
// is true but the detected terminal does not support colors, then the list of
|
||||
// mage targets will be displayed in the default colors (e.g. black and white).
|
||||
const EnableColorEnv = "MAGEFILE_ENABLE_COLOR"
|
||||
|
||||
// TargetColorEnv is the environment variable that indicates which ANSI color
|
||||
// should be used to colorize mage targets. This is only applicable when
|
||||
// the MAGEFILE_ENABLE_COLOR environment variable is true.
|
||||
// The supported ANSI color names are any of these:
|
||||
// - Black
|
||||
// - Red
|
||||
// - Green
|
||||
// - Yellow
|
||||
// - Blue
|
||||
// - Magenta
|
||||
// - Cyan
|
||||
// - White
|
||||
// - BrightBlack
|
||||
// - BrightRed
|
||||
// - BrightGreen
|
||||
// - BrightYellow
|
||||
// - BrightBlue
|
||||
// - BrightMagenta
|
||||
// - BrightCyan
|
||||
// - BrightWhite
|
||||
const TargetColorEnv = "MAGEFILE_TARGET_COLOR"
|
||||
|
||||
// Verbose reports whether a magefile was run with the verbose flag.
|
||||
func Verbose() bool {
|
||||
b, _ := strconv.ParseBool(os.Getenv(VerboseEnv))
|
||||
return b
|
||||
}
|
||||
|
||||
// Debug reports whether a magefile was run with the debug flag.
|
||||
func Debug() bool {
|
||||
b, _ := strconv.ParseBool(os.Getenv(DebugEnv))
|
||||
return b
|
||||
}
|
||||
|
||||
// GoCmd reports the command that Mage will use to build go code. By default mage runs
|
||||
// the "go" binary in the PATH.
|
||||
func GoCmd() string {
|
||||
if cmd := os.Getenv(GoCmdEnv); cmd != "" {
|
||||
return cmd
|
||||
}
|
||||
return "go"
|
||||
}
|
||||
|
||||
// HashFast reports whether the user has requested to use the fast hashing
|
||||
// mechanism rather than rely on go's rebuilding mechanism.
|
||||
func HashFast() bool {
|
||||
b, _ := strconv.ParseBool(os.Getenv(HashFastEnv))
|
||||
return b
|
||||
}
|
||||
|
||||
// IgnoreDefault reports whether the user has requested to ignore the default target
|
||||
// in the magefile.
|
||||
func IgnoreDefault() bool {
|
||||
b, _ := strconv.ParseBool(os.Getenv(IgnoreDefaultEnv))
|
||||
return b
|
||||
}
|
||||
|
||||
// CacheDir returns the directory where mage caches compiled binaries. It
|
||||
// defaults to $HOME/.magefile, but may be overridden by the MAGEFILE_CACHE
|
||||
// environment variable.
|
||||
func CacheDir() string {
|
||||
d := os.Getenv(CacheEnv)
|
||||
if d != "" {
|
||||
return d
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return filepath.Join(os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"), "magefile")
|
||||
default:
|
||||
return filepath.Join(os.Getenv("HOME"), ".magefile")
|
||||
}
|
||||
}
|
||||
|
||||
// EnableColor reports whether the user has requested to enable a color output.
|
||||
func EnableColor() bool {
|
||||
b, _ := strconv.ParseBool(os.Getenv(EnableColorEnv))
|
||||
return b
|
||||
}
|
||||
|
||||
// TargetColor returns the configured ANSI color name a color output.
|
||||
func TargetColor() string {
|
||||
s, exists := os.LookupEnv(TargetColorEnv)
|
||||
if exists {
|
||||
if c, ok := getAnsiColor(s); ok {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return DefaultTargetAnsiColor
|
||||
}
|
||||
|
||||
// Namespace allows for the grouping of similar commands
|
||||
type Namespace struct{}
|
|
@ -1,177 +0,0 @@
|
|||
package sh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
)
|
||||
|
||||
// RunCmd returns a function that will call Run with the given command. This is
|
||||
// useful for creating command aliases to make your scripts easier to read, like
|
||||
// this:
|
||||
//
|
||||
// // in a helper file somewhere
|
||||
// var g0 = sh.RunCmd("go") // go is a keyword :(
|
||||
//
|
||||
// // somewhere in your main code
|
||||
// if err := g0("install", "github.com/gohugo/hugo"); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// Args passed to command get baked in as args to the command when you run it.
|
||||
// Any args passed in when you run the returned function will be appended to the
|
||||
// original args. For example, this is equivalent to the above:
|
||||
//
|
||||
// var goInstall = sh.RunCmd("go", "install") goInstall("github.com/gohugo/hugo")
|
||||
//
|
||||
// RunCmd uses Exec underneath, so see those docs for more details.
|
||||
func RunCmd(cmd string, args ...string) func(args ...string) error {
|
||||
return func(args2 ...string) error {
|
||||
return Run(cmd, append(args, args2...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// OutCmd is like RunCmd except the command returns the output of the
|
||||
// command.
|
||||
func OutCmd(cmd string, args ...string) func(args ...string) (string, error) {
|
||||
return func(args2 ...string) (string, error) {
|
||||
return Output(cmd, append(args, args2...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Run is like RunWith, but doesn't specify any environment variables.
|
||||
func Run(cmd string, args ...string) error {
|
||||
return RunWith(nil, cmd, args...)
|
||||
}
|
||||
|
||||
// RunV is like Run, but always sends the command's stdout to os.Stdout.
|
||||
func RunV(cmd string, args ...string) error {
|
||||
_, err := Exec(nil, os.Stdout, os.Stderr, cmd, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// RunWith runs the given command, directing stderr to this program's stderr and
|
||||
// printing stdout to stdout if mage was run with -v. It adds adds env to the
|
||||
// environment variables for the command being run. Environment variables should
|
||||
// be in the format name=value.
|
||||
func RunWith(env map[string]string, cmd string, args ...string) error {
|
||||
var output io.Writer
|
||||
if mg.Verbose() {
|
||||
output = os.Stdout
|
||||
}
|
||||
_, err := Exec(env, output, os.Stderr, cmd, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// RunWithV is like RunWith, but always sends the command's stdout to os.Stdout.
|
||||
func RunWithV(env map[string]string, cmd string, args ...string) error {
|
||||
_, err := Exec(env, os.Stdout, os.Stderr, cmd, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Output runs the command and returns the text from stdout.
|
||||
func Output(cmd string, args ...string) (string, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := Exec(nil, buf, os.Stderr, cmd, args...)
|
||||
return strings.TrimSuffix(buf.String(), "\n"), err
|
||||
}
|
||||
|
||||
// OutputWith is like RunWith, but returns what is written to stdout.
|
||||
func OutputWith(env map[string]string, cmd string, args ...string) (string, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
_, err := Exec(env, buf, os.Stderr, cmd, args...)
|
||||
return strings.TrimSuffix(buf.String(), "\n"), err
|
||||
}
|
||||
|
||||
// Exec executes the command, piping its stderr to mage's stderr and
|
||||
// piping its stdout to the given writer. If the command fails, it will return
|
||||
// an error that, if returned from a target or mg.Deps call, will cause mage to
|
||||
// exit with the same code as the command failed with. Env is a list of
|
||||
// environment variables to set when running the command, these override the
|
||||
// current environment variables set (which are also passed to the command). cmd
|
||||
// and args may include references to environment variables in $FOO format, in
|
||||
// which case these will be expanded before the command is run.
|
||||
//
|
||||
// Ran reports if the command ran (rather than was not found or not executable).
|
||||
// Code reports the exit code the command returned if it ran. If err == nil, ran
|
||||
// is always true and code is always 0.
|
||||
func Exec(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, err error) {
|
||||
expand := func(s string) string {
|
||||
s2, ok := env[s]
|
||||
if ok {
|
||||
return s2
|
||||
}
|
||||
return os.Getenv(s)
|
||||
}
|
||||
cmd = os.Expand(cmd, expand)
|
||||
for i := range args {
|
||||
args[i] = os.Expand(args[i], expand)
|
||||
}
|
||||
ran, code, err := run(env, stdout, stderr, cmd, args...)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if ran {
|
||||
return ran, mg.Fatalf(code, `running "%s %s" failed with exit code %d`, cmd, strings.Join(args, " "), code)
|
||||
}
|
||||
return ran, fmt.Errorf(`failed to run "%s %s: %v"`, cmd, strings.Join(args, " "), err)
|
||||
}
|
||||
|
||||
func run(env map[string]string, stdout, stderr io.Writer, cmd string, args ...string) (ran bool, code int, err error) {
|
||||
c := exec.Command(cmd, args...)
|
||||
c.Env = os.Environ()
|
||||
for k, v := range env {
|
||||
c.Env = append(c.Env, k+"="+v)
|
||||
}
|
||||
c.Stderr = stderr
|
||||
c.Stdout = stdout
|
||||
c.Stdin = os.Stdin
|
||||
log.Println("exec:", cmd, strings.Join(args, " "))
|
||||
err = c.Run()
|
||||
return CmdRan(err), ExitStatus(err), err
|
||||
}
|
||||
|
||||
// CmdRan examines the error to determine if it was generated as a result of a
|
||||
// command running via os/exec.Command. If the error is nil, or the command ran
|
||||
// (even if it exited with a non-zero exit code), CmdRan reports true. If the
|
||||
// error is an unrecognized type, or it is an error from exec.Command that says
|
||||
// the command failed to run (usually due to the command not existing or not
|
||||
// being executable), it reports false.
|
||||
func CmdRan(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
ee, ok := err.(*exec.ExitError)
|
||||
if ok {
|
||||
return ee.Exited()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type exitStatus interface {
|
||||
ExitStatus() int
|
||||
}
|
||||
|
||||
// ExitStatus returns the exit status of the error if it is an exec.ExitError
|
||||
// or if it implements ExitStatus() int.
|
||||
// 0 if it is nil or 1 if it is a different error.
|
||||
func ExitStatus(err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
if e, ok := err.(exitStatus); ok {
|
||||
return e.ExitStatus()
|
||||
}
|
||||
if e, ok := err.(*exec.ExitError); ok {
|
||||
if ex, ok := e.Sys().(exitStatus); ok {
|
||||
return ex.ExitStatus()
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package sh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Rm removes the given file or directory even if non-empty. It will not return
|
||||
// an error if the target doesn't exist, only if the target cannot be removed.
|
||||
func Rm(path string) error {
|
||||
err := os.RemoveAll(path)
|
||||
if err == nil || os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf(`failed to remove %s: %v`, path, err)
|
||||
}
|
||||
|
||||
// Copy robustly copies the source file to the destination, overwriting the destination if necessary.
|
||||
func Copy(dst string, src string) error {
|
||||
from, err := os.Open(src)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`can't copy %s: %v`, src, err)
|
||||
}
|
||||
defer from.Close()
|
||||
finfo, err := from.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf(`can't stat %s: %v`, src, err)
|
||||
}
|
||||
to, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, finfo.Mode())
|
||||
if err != nil {
|
||||
return fmt.Errorf(`can't copy to %s: %v`, dst, err)
|
||||
}
|
||||
defer to.Close()
|
||||
_, err = io.Copy(to, from)
|
||||
if err != nil {
|
||||
return fmt.Errorf(`error copying %s to %s: %v`, src, dst, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
*.o
|
||||
*.a
|
||||
*.so
|
||||
*.out
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
|
@ -22,3 +23,6 @@ _testmain.go
|
|||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
# test editor files
|
||||
*.swp
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
## Release 0.1.0 (UNRELEASED)
|
|
@ -4,3 +4,68 @@
|
|||
A Golang Matrix client.
|
||||
|
||||
**THIS IS UNDER ACTIVE DEVELOPMENT: BREAKING CHANGES ARE FREQUENT.**
|
||||
|
||||
# Contributing
|
||||
|
||||
All contributions are greatly appreciated!
|
||||
|
||||
## How to report issues
|
||||
|
||||
Please check the current open issues for similar reports
|
||||
in order to avoid duplicates.
|
||||
|
||||
Some general guidelines:
|
||||
|
||||
- Include a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) when possible.
|
||||
- Describe the expected behaviour and what actually happened
|
||||
including a full trace-back in case of exceptions.
|
||||
- Make sure to list details about your environment
|
||||
|
||||
## Setting up your environment
|
||||
|
||||
If you intend to contribute to gomatrix you'll first need Go installed on your machine (version 1.12+ is required). Also, make sure to have golangci-lint properly set up since we use it for pre-commit hooks (for instructions on how to install it, check the [official docs](https://golangci-lint.run/usage/install/#local-installation)).
|
||||
|
||||
- Fork gomatrix to your GitHub account by clicking the [Fork](https://github.com/matrix-org/gomatrix/fork) button.
|
||||
- [Clone](https://help.github.com/en/articles/fork-a-repo#step-2-create-a-local-clone-of-your-fork) the main repository (not your fork) to your local machine.
|
||||
|
||||
|
||||
$ git clone https://github.com/matrix-org/gomatrix
|
||||
$ cd gomatrix
|
||||
|
||||
|
||||
- Add your fork as a remote to push your contributions.Replace
|
||||
``{username}`` with your username.
|
||||
|
||||
git remote add fork https://github.com/{username}/gomatrix
|
||||
|
||||
- Create a new branch to identify what feature you are working on.
|
||||
|
||||
$ git fetch origin
|
||||
$ git checkout -b your-branch-name origin/master
|
||||
|
||||
|
||||
- Make your changes, including tests that cover any code changes you make, and run them as described below.
|
||||
|
||||
- Execute pre-commit hooks by running
|
||||
|
||||
<gomatrix dir>/hooks/pre-commit
|
||||
|
||||
- Push your changes to your fork and [create a pull request](https://help.github.com/en/articles/creating-a-pull-request) describing your changes.
|
||||
|
||||
$ git push --set-upstream fork your-branch-name
|
||||
|
||||
- Finally, create a [pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
|
||||
|
||||
## How to run tests
|
||||
|
||||
You can run the test suite and example code with `$ go test -v`
|
||||
|
||||
# Running Coverage
|
||||
|
||||
To run coverage, first generate the coverage report using `go test`
|
||||
|
||||
go test -v -cover -coverprofile=coverage.out
|
||||
|
||||
You can now show the generated report as a html page with `go tool`
|
||||
|
||||
go tool cover -html=coverage.out
|
||||
|
|
|
@ -53,13 +53,13 @@ func (e HTTPError) Error() string {
|
|||
return fmt.Sprintf("contents=%v msg=%s code=%d wrapped=%s", e.Contents, e.Message, e.Code, wrappedErrMsg)
|
||||
}
|
||||
|
||||
// BuildURL builds a URL with the Client's homserver/prefix/access_token set already.
|
||||
// BuildURL builds a URL with the Client's homeserver/prefix set already.
|
||||
func (cli *Client) BuildURL(urlPath ...string) string {
|
||||
ps := append([]string{cli.Prefix}, urlPath...)
|
||||
return cli.BuildBaseURL(ps...)
|
||||
}
|
||||
|
||||
// BuildBaseURL builds a URL with the Client's homeserver/access_token set already. You must
|
||||
// BuildBaseURL builds a URL with the Client's homeserver set already. You must
|
||||
// supply the prefix in the path.
|
||||
func (cli *Client) BuildBaseURL(urlPath ...string) string {
|
||||
// copy the URL. Purposefully ignore error as the input is from a valid URL already
|
||||
|
@ -72,9 +72,6 @@ func (cli *Client) BuildBaseURL(urlPath ...string) string {
|
|||
hsURL.Path = hsURL.Path + "/"
|
||||
}
|
||||
query := hsURL.Query()
|
||||
if cli.AccessToken != "" {
|
||||
query.Set("access_token", cli.AccessToken)
|
||||
}
|
||||
if cli.AppServiceUserID != "" {
|
||||
query.Set("user_id", cli.AppServiceUserID)
|
||||
}
|
||||
|
@ -82,7 +79,7 @@ func (cli *Client) BuildBaseURL(urlPath ...string) string {
|
|||
return hsURL.String()
|
||||
}
|
||||
|
||||
// BuildURLWithQuery builds a URL with query parameters in addition to the Client's homeserver/prefix/access_token set already.
|
||||
// BuildURLWithQuery builds a URL with query parameters in addition to the Client's homeserver/prefix set already.
|
||||
func (cli *Client) BuildURLWithQuery(urlPath []string, urlQuery map[string]string) string {
|
||||
u, _ := url.Parse(cli.BuildURL(urlPath...))
|
||||
q := u.Query()
|
||||
|
@ -203,7 +200,13 @@ func (cli *Client) MakeRequest(method string, httpURL string, reqBody interface{
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
if cli.AccessToken != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+cli.AccessToken)
|
||||
}
|
||||
|
||||
res, err := cli.Client.Do(req)
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
|
@ -687,15 +690,21 @@ func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, co
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", contentType)
|
||||
req.Header.Set("Authorization", "Bearer "+cli.AccessToken)
|
||||
|
||||
req.ContentLength = contentLength
|
||||
|
||||
res, err := cli.Client.Do(req)
|
||||
if res != nil {
|
||||
defer res.Body.Close()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
contents, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
|
@ -710,10 +719,12 @@ func (cli *Client) UploadToContentRepo(content io.Reader, contentType string, co
|
|||
Code: res.StatusCode,
|
||||
}
|
||||
}
|
||||
|
||||
var m RespMediaUpload
|
||||
if err := json.NewDecoder(res.Body).Decode(&m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -77,8 +77,8 @@ type Attachment struct {
|
|||
// https://rocket.chat/docs/developer-guides/rest-api/chat/postmessage/
|
||||
type AttachmentField struct {
|
||||
Short bool `json:"short"`
|
||||
Title string `json:"title"`
|
||||
Value string `json:"value"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
type AttachmentActionType string
|
||||
|
@ -89,15 +89,15 @@ const (
|
|||
|
||||
// AttachmentAction are action buttons on message attachments
|
||||
type AttachmentAction struct {
|
||||
Type AttachmentActionType `json:"type"`
|
||||
Text string `json:"text"`
|
||||
Url string `json:"url"`
|
||||
ImageURL string `json:"image_url"`
|
||||
Type AttachmentActionType `json:"type,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Url string `json:"url,omitempty"`
|
||||
ImageURL string `json:"image_url,omitempty"`
|
||||
IsWebView bool `json:"is_webview"`
|
||||
WebviewHeightRatio string `json:"webview_height_ratio"`
|
||||
Msg string `json:"msg"`
|
||||
WebviewHeightRatio string `json:"webview_height_ratio,omitempty"`
|
||||
Msg string `json:"msg,omitempty"`
|
||||
MsgInChatWindow bool `json:"msg_in_chat_window"`
|
||||
MsgProcessingType MessageProcessingType `json:"msg_processing_type"`
|
||||
MsgProcessingType MessageProcessingType `json:"msg_processing_type,omitempty"`
|
||||
}
|
||||
|
||||
// AttachmentActionButtonAlignment configures how the actions buttons will be aligned
|
||||
|
|
|
@ -19,6 +19,17 @@ type ChannelResponse struct {
|
|||
Channel models.Channel `json:"channel"`
|
||||
}
|
||||
|
||||
type GroupsResponse struct {
|
||||
Status
|
||||
models.Pagination
|
||||
Groups []models.Channel `json:"groups"`
|
||||
}
|
||||
|
||||
type GroupResponse struct {
|
||||
Status
|
||||
Group models.Channel `json:"group"`
|
||||
}
|
||||
|
||||
// GetPublicChannels returns all channels that can be seen by the logged in user.
|
||||
//
|
||||
// https://rocket.chat/docs/developer-guides/rest-api/channels/list
|
||||
|
@ -31,6 +42,19 @@ func (c *Client) GetPublicChannels() (*ChannelsResponse, error) {
|
|||
return response, nil
|
||||
}
|
||||
|
||||
// GetPrivateGroups returns all channels that can be seen by the logged in user.
|
||||
//
|
||||
// https://rocket.chat/docs/developer-guides/rest-api/groups/list
|
||||
func (c *Client) GetPrivateGroups() (*GroupsResponse, error) {
|
||||
response := new(GroupsResponse)
|
||||
if err := c.Get("groups.list", nil, response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
||||
// GetJoinedChannels returns all channels that the user has joined.
|
||||
//
|
||||
// https://rocket.chat/docs/developer-guides/rest-api/channels/list-joined
|
||||
|
@ -70,3 +94,20 @@ func (c *Client) GetChannelInfo(channel *models.Channel) (*models.Channel, error
|
|||
return &response.Channel, nil
|
||||
}
|
||||
|
||||
// GetGroupInfo get information about a group. That might be useful to update the usernames.
|
||||
//
|
||||
// https://rocket.chat/docs/developer-guides/rest-api/groups/info
|
||||
func (c *Client) GetGroupInfo(channel *models.Channel) (*models.Channel, error) {
|
||||
response := new(GroupResponse)
|
||||
switch {
|
||||
case channel.Name != "" && channel.ID == "":
|
||||
if err := c.Get("groups.info", url.Values{"roomName": []string{channel.Name}}, response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
if err := c.Get("groups.info", url.Values{"roomId": []string{channel.ID}}, response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &response.Group, nil
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,9 +2,9 @@
|
|||
|
||||
[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/xid) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/xid/master/LICENSE) [![Build Status](https://travis-ci.org/rs/xid.svg?branch=master)](https://travis-ci.org/rs/xid) [![Coverage](http://gocover.io/_badge/github.com/rs/xid)](http://gocover.io/github.com/rs/xid)
|
||||
|
||||
Package xid is a globally unique id generator library, ready to be used safely directly in your server code.
|
||||
Package xid is a globally unique id generator library, ready to safely be used directly in your server code.
|
||||
|
||||
Xid is using Mongo Object ID algorithm to generate globally unique ids with a different serialization (base64) to make it shorter when transported as a string:
|
||||
Xid uses the Mongo Object ID algorithm to generate globally unique ids with a different serialization (base64) to make it shorter when transported as a string:
|
||||
https://docs.mongodb.org/manual/reference/object-id/
|
||||
|
||||
- 4-byte value representing the seconds since the Unix epoch,
|
||||
|
@ -33,7 +33,7 @@ is required so it can be used directly in server's code.
|
|||
|-------------|-------------|----------------|----------------
|
||||
| [UUID] | 16 bytes | 36 chars | configuration free, not sortable
|
||||
| [shortuuid] | 16 bytes | 22 chars | configuration free, not sortable
|
||||
| [Snowflake] | 8 bytes | up to 20 chars | needs machin/DC configuration, needs central server, sortable
|
||||
| [Snowflake] | 8 bytes | up to 20 chars | needs machine/DC configuration, needs central server, sortable
|
||||
| [MongoID] | 12 bytes | 24 chars | configuration free, sortable
|
||||
| xid | 12 bytes | 20 chars | configuration free, sortable
|
||||
|
||||
|
@ -57,7 +57,7 @@ Best used with [zerolog](https://github.com/rs/zerolog)'s
|
|||
|
||||
Notes:
|
||||
|
||||
- Xid is dependent on the system time, a monotonic counter and so is not cryptographically secure. If unpredictability of IDs is important, you should not use Xids. It is worth noting that most of the other UUID like implementations are also not cryptographically secure. You shoud use libraries that rely on cryptographically secure sources (like /dev/urandom on unix, crypto/rand in golang), if you want a truly random ID generator.
|
||||
- Xid is dependent on the system time, a monotonic counter and so is not cryptographically secure. If unpredictability of IDs is important, you should not use Xids. It is worth noting that most other UUID-like implementations are also not cryptographically secure. You should use libraries that rely on cryptographically secure sources (like /dev/urandom on unix, crypto/rand in golang), if you want a truly random ID generator.
|
||||
|
||||
References:
|
||||
|
||||
|
@ -66,6 +66,9 @@ References:
|
|||
- https://blog.twitter.com/2010/announcing-snowflake
|
||||
- Python port by [Graham Abbott](https://github.com/graham): https://github.com/graham/python_xid
|
||||
- Scala port by [Egor Kolotaev](https://github.com/kolotaev): https://github.com/kolotaev/ride
|
||||
- Rust port by [Jérôme Renard](https://github.com/jeromer/): https://github.com/jeromer/libxid
|
||||
- Ruby port by [Valar](https://github.com/valarpirai/): https://github.com/valarpirai/ruby_xid
|
||||
- Java port by [0xShamil](https://github.com/0xShamil/): https://github.com/0xShamil/java-xid
|
||||
|
||||
## Install
|
||||
|
||||
|
@ -105,7 +108,7 @@ BenchmarkUUIDv4-2 1000000 1427 ns/op 64 B/op 2 allocs/op
|
|||
BenchmarkUUIDv4-4 1000000 1452 ns/op 64 B/op 2 allocs/op
|
||||
```
|
||||
|
||||
Note: UUIDv1 requires a global lock, hence the performence degrading as we add more CPUs.
|
||||
Note: UUIDv1 requires a global lock, hence the performance degradation as we add more CPUs.
|
||||
|
||||
## Licenses
|
||||
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
module github.com/rs/xid
|
||||
|
||||
go 1.12
|
||||
|
|
|
@ -5,6 +5,9 @@ package xid
|
|||
import "io/ioutil"
|
||||
|
||||
func readPlatformMachineID() (string, error) {
|
||||
b, err := ioutil.ReadFile("/sys/class/dmi/id/product_uuid")
|
||||
b, err := ioutil.ReadFile("/etc/machine-id")
|
||||
if err != nil || len(b) == 0 {
|
||||
b, err = ioutil.ReadFile("/sys/class/dmi/id/product_uuid")
|
||||
}
|
||||
return string(b), err
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import (
|
|||
"sort"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Code inspired from mgo/bson ObjectId
|
||||
|
@ -177,7 +178,13 @@ func FromString(id string) (ID, error) {
|
|||
func (id ID) String() string {
|
||||
text := make([]byte, encodedLen)
|
||||
encode(text, id[:])
|
||||
return string(text)
|
||||
return *(*string)(unsafe.Pointer(&text))
|
||||
}
|
||||
|
||||
// Encode encodes the id using base32 encoding, writing 20 bytes to dst and return it.
|
||||
func (id ID) Encode(dst []byte) []byte {
|
||||
encode(dst, id[:])
|
||||
return dst
|
||||
}
|
||||
|
||||
// MarshalText implements encoding/text TextMarshaler interface
|
||||
|
@ -192,32 +199,37 @@ func (id ID) MarshalJSON() ([]byte, error) {
|
|||
if id.IsNil() {
|
||||
return []byte("null"), nil
|
||||
}
|
||||
text, err := id.MarshalText()
|
||||
return []byte(`"` + string(text) + `"`), err
|
||||
text := make([]byte, encodedLen+2)
|
||||
encode(text[1:encodedLen+1], id[:])
|
||||
text[0], text[encodedLen+1] = '"', '"'
|
||||
return text, nil
|
||||
}
|
||||
|
||||
// encode by unrolling the stdlib base32 algorithm + removing all safe checks
|
||||
func encode(dst, id []byte) {
|
||||
dst[0] = encoding[id[0]>>3]
|
||||
dst[1] = encoding[(id[1]>>6)&0x1F|(id[0]<<2)&0x1F]
|
||||
dst[2] = encoding[(id[1]>>1)&0x1F]
|
||||
dst[3] = encoding[(id[2]>>4)&0x1F|(id[1]<<4)&0x1F]
|
||||
dst[4] = encoding[id[3]>>7|(id[2]<<1)&0x1F]
|
||||
dst[5] = encoding[(id[3]>>2)&0x1F]
|
||||
dst[6] = encoding[id[4]>>5|(id[3]<<3)&0x1F]
|
||||
dst[7] = encoding[id[4]&0x1F]
|
||||
dst[8] = encoding[id[5]>>3]
|
||||
dst[9] = encoding[(id[6]>>6)&0x1F|(id[5]<<2)&0x1F]
|
||||
dst[10] = encoding[(id[6]>>1)&0x1F]
|
||||
dst[11] = encoding[(id[7]>>4)&0x1F|(id[6]<<4)&0x1F]
|
||||
dst[12] = encoding[id[8]>>7|(id[7]<<1)&0x1F]
|
||||
dst[13] = encoding[(id[8]>>2)&0x1F]
|
||||
dst[14] = encoding[(id[9]>>5)|(id[8]<<3)&0x1F]
|
||||
dst[15] = encoding[id[9]&0x1F]
|
||||
dst[16] = encoding[id[10]>>3]
|
||||
dst[17] = encoding[(id[11]>>6)&0x1F|(id[10]<<2)&0x1F]
|
||||
dst[18] = encoding[(id[11]>>1)&0x1F]
|
||||
_ = dst[19]
|
||||
_ = id[11]
|
||||
|
||||
dst[19] = encoding[(id[11]<<4)&0x1F]
|
||||
dst[18] = encoding[(id[11]>>1)&0x1F]
|
||||
dst[17] = encoding[(id[11]>>6)&0x1F|(id[10]<<2)&0x1F]
|
||||
dst[16] = encoding[id[10]>>3]
|
||||
dst[15] = encoding[id[9]&0x1F]
|
||||
dst[14] = encoding[(id[9]>>5)|(id[8]<<3)&0x1F]
|
||||
dst[13] = encoding[(id[8]>>2)&0x1F]
|
||||
dst[12] = encoding[id[8]>>7|(id[7]<<1)&0x1F]
|
||||
dst[11] = encoding[(id[7]>>4)&0x1F|(id[6]<<4)&0x1F]
|
||||
dst[10] = encoding[(id[6]>>1)&0x1F]
|
||||
dst[9] = encoding[(id[6]>>6)&0x1F|(id[5]<<2)&0x1F]
|
||||
dst[8] = encoding[id[5]>>3]
|
||||
dst[7] = encoding[id[4]&0x1F]
|
||||
dst[6] = encoding[id[4]>>5|(id[3]<<3)&0x1F]
|
||||
dst[5] = encoding[(id[3]>>2)&0x1F]
|
||||
dst[4] = encoding[id[3]>>7|(id[2]<<1)&0x1F]
|
||||
dst[3] = encoding[(id[2]>>4)&0x1F|(id[1]<<4)&0x1F]
|
||||
dst[2] = encoding[(id[1]>>1)&0x1F]
|
||||
dst[1] = encoding[(id[1]>>6)&0x1F|(id[0]<<2)&0x1F]
|
||||
dst[0] = encoding[id[0]>>3]
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding/text TextUnmarshaler interface
|
||||
|
@ -246,18 +258,21 @@ func (id *ID) UnmarshalJSON(b []byte) error {
|
|||
|
||||
// decode by unrolling the stdlib base32 algorithm + removing all safe checks
|
||||
func decode(id *ID, src []byte) {
|
||||
id[0] = dec[src[0]]<<3 | dec[src[1]]>>2
|
||||
id[1] = dec[src[1]]<<6 | dec[src[2]]<<1 | dec[src[3]]>>4
|
||||
id[2] = dec[src[3]]<<4 | dec[src[4]]>>1
|
||||
id[3] = dec[src[4]]<<7 | dec[src[5]]<<2 | dec[src[6]]>>3
|
||||
id[4] = dec[src[6]]<<5 | dec[src[7]]
|
||||
id[5] = dec[src[8]]<<3 | dec[src[9]]>>2
|
||||
id[6] = dec[src[9]]<<6 | dec[src[10]]<<1 | dec[src[11]]>>4
|
||||
id[7] = dec[src[11]]<<4 | dec[src[12]]>>1
|
||||
id[8] = dec[src[12]]<<7 | dec[src[13]]<<2 | dec[src[14]]>>3
|
||||
id[9] = dec[src[14]]<<5 | dec[src[15]]
|
||||
id[10] = dec[src[16]]<<3 | dec[src[17]]>>2
|
||||
_ = src[19]
|
||||
_ = id[11]
|
||||
|
||||
id[11] = dec[src[17]]<<6 | dec[src[18]]<<1 | dec[src[19]]>>4
|
||||
id[10] = dec[src[16]]<<3 | dec[src[17]]>>2
|
||||
id[9] = dec[src[14]]<<5 | dec[src[15]]
|
||||
id[8] = dec[src[12]]<<7 | dec[src[13]]<<2 | dec[src[14]]>>3
|
||||
id[7] = dec[src[11]]<<4 | dec[src[12]]>>1
|
||||
id[6] = dec[src[9]]<<6 | dec[src[10]]<<1 | dec[src[11]]>>4
|
||||
id[5] = dec[src[8]]<<3 | dec[src[9]]>>2
|
||||
id[4] = dec[src[6]]<<5 | dec[src[7]]
|
||||
id[3] = dec[src[4]]<<7 | dec[src[5]]<<2 | dec[src[6]]>>3
|
||||
id[2] = dec[src[3]]<<4 | dec[src[4]]>>1
|
||||
id[1] = dec[src[1]]<<6 | dec[src[2]]<<1 | dec[src[3]]>>4
|
||||
id[0] = dec[src[0]]<<3 | dec[src[1]]>>2
|
||||
}
|
||||
|
||||
// Time returns the timestamp part of the id.
|
||||
|
|
|
@ -9,6 +9,7 @@ os: linux
|
|||
install:
|
||||
- ./travis/install.sh
|
||||
script:
|
||||
- go run mage.go -v crossBuild
|
||||
- go run mage.go lint
|
||||
- go run mage.go test
|
||||
- cd ci
|
||||
- go run mage.go -v -w ../ crossBuild
|
||||
- go run mage.go -v -w ../ lint
|
||||
- go run mage.go -v -w ../ test
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
# 1.8.1
|
||||
Code quality:
|
||||
* move magefile in its own subdir/submodule to remove magefile dependency on logrus consumer
|
||||
* improve timestamp format documentation
|
||||
|
||||
Fixes:
|
||||
* fix race condition on logger hooks
|
||||
|
||||
|
||||
# 1.8.0
|
||||
|
||||
Correct versioning number replacing v1.7.1.
|
||||
|
|
|
@ -261,7 +261,15 @@ func (entry *Entry) log(level Level, msg string) {
|
|||
}
|
||||
|
||||
func (entry *Entry) fireHooks() {
|
||||
err := entry.Logger.Hooks.Fire(entry.Level, entry)
|
||||
var tmpHooks LevelHooks
|
||||
entry.Logger.mu.Lock()
|
||||
tmpHooks = make(LevelHooks, len(entry.Logger.Hooks))
|
||||
for k, v := range entry.Logger.Hooks {
|
||||
tmpHooks[k] = v
|
||||
}
|
||||
entry.Logger.mu.Unlock()
|
||||
|
||||
err := tmpHooks.Fire(entry.Level, entry)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ module github.com/sirupsen/logrus
|
|||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/magefile/mage v1.10.0
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
|
||||
github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
|
@ -23,6 +23,9 @@ func (f FieldMap) resolve(key fieldKey) string {
|
|||
// JSONFormatter formats logs into parsable json
|
||||
type JSONFormatter struct {
|
||||
// TimestampFormat sets the format used for marshaling timestamps.
|
||||
// The format to use is the same than for time.Format or time.Parse from the standard
|
||||
// library.
|
||||
// The standard Library already provides a set of predefined format.
|
||||
TimestampFormat string
|
||||
|
||||
// DisableTimestamp allows disabling automatic timestamps in output
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
// +build mage
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
"github.com/magefile/mage/sh"
|
||||
)
|
||||
|
||||
// getBuildMatrix returns the build matrix from the current version of the go compiler
|
||||
func getBuildMatrix() (map[string][]string, error) {
|
||||
jsonData, err := sh.Output("go", "tool", "dist", "list", "-json")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data []struct {
|
||||
Goos string
|
||||
Goarch string
|
||||
}
|
||||
if err := json.Unmarshal([]byte(jsonData), &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
matrix := map[string][]string{}
|
||||
for _, v := range data {
|
||||
if val, ok := matrix[v.Goos]; ok {
|
||||
matrix[v.Goos] = append(val, v.Goarch)
|
||||
} else {
|
||||
matrix[v.Goos] = []string{v.Goarch}
|
||||
}
|
||||
}
|
||||
|
||||
return matrix, nil
|
||||
}
|
||||
|
||||
func CrossBuild() error {
|
||||
matrix, err := getBuildMatrix()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for os, arches := range matrix {
|
||||
for _, arch := range arches {
|
||||
env := map[string]string{
|
||||
"GOOS": os,
|
||||
"GOARCH": arch,
|
||||
}
|
||||
if mg.Verbose() {
|
||||
fmt.Printf("Building for GOOS=%s GOARCH=%s\n", os, arch)
|
||||
}
|
||||
if err := sh.RunWith(env, "go", "build", "./..."); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Lint() error {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
if gopath == "" {
|
||||
return fmt.Errorf("cannot retrieve GOPATH")
|
||||
}
|
||||
|
||||
return sh.Run(path.Join(gopath, "bin", "golangci-lint"), "run", "./...")
|
||||
}
|
||||
|
||||
// Run the test suite
|
||||
func Test() error {
|
||||
return sh.RunWith(map[string]string{"GORACE": "halt_on_error=1"},
|
||||
"go", "test", "-race", "-v", "./...")
|
||||
}
|
|
@ -53,7 +53,10 @@ type TextFormatter struct {
|
|||
// the time passed since beginning of execution.
|
||||
FullTimestamp bool
|
||||
|
||||
// TimestampFormat to use for display when a full timestamp is printed
|
||||
// TimestampFormat to use for display when a full timestamp is printed.
|
||||
// The format to use is the same than for time.Format or time.Parse from the standard
|
||||
// library.
|
||||
// The standard Library already provides a set of predefined format.
|
||||
TimestampFormat string
|
||||
|
||||
// The fields are sorted by default for a consistent output. For applications
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
# ring
|
||||
|
||||
[![GoDoc](https://godoc.org/github.com/zfjagann/golang-ring?status.svg)](https://godoc.org/github.com/zfjagann/golang-ring)
|
||||
|
||||
--
|
||||
import "github.com/zfjagann/golang-ring"
|
||||
import "github.com/zealws/golang-ring"
|
||||
|
||||
Package ring provides a simple implementation of a ring buffer.
|
||||
|
||||
|
@ -20,19 +17,27 @@ Changing this value only affects ring buffers created after it is changed.
|
|||
|
||||
```go
|
||||
type Ring struct {
|
||||
sync.Mutex
|
||||
}
|
||||
```
|
||||
|
||||
Type Ring implements a Circular Buffer. The default value of the Ring struct is
|
||||
a valid (empty) Ring buffer with capacity DefaultCapacify.
|
||||
|
||||
#### func (Ring) Capacity
|
||||
#### func (*Ring) Capacity
|
||||
|
||||
```go
|
||||
func (r Ring) Capacity() int
|
||||
func (r *Ring) Capacity() int
|
||||
```
|
||||
Capacity returns the current capacity of the ring buffer.
|
||||
|
||||
#### func (*Ring) ContentSize
|
||||
|
||||
```go
|
||||
func (r *Ring) ContentSize() int
|
||||
```
|
||||
ContentSize returns the current number of elements inside the ring buffer.
|
||||
|
||||
#### func (*Ring) Dequeue
|
||||
|
||||
```go
|
||||
|
|
|
@ -160,7 +160,11 @@ func (r *Ring) get(p int) interface{} {
|
|||
|
||||
// returns the modified index of an unmodified index
|
||||
func (r *Ring) mod(p int) int {
|
||||
return p % len(r.buff)
|
||||
v := p % len(r.buff)
|
||||
for v < 0 { // this bit fixes negative indices
|
||||
v += len(r.buff)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (r *Ring) checkInit() {
|
||||
|
@ -178,12 +182,53 @@ func (r *Ring) checkInit() {
|
|||
func (r *Ring) extend(size int) {
|
||||
if size == len(r.buff) {
|
||||
return
|
||||
} else if size < len(r.buff) {
|
||||
r.buff = r.buff[0:size]
|
||||
}
|
||||
|
||||
if size < len(r.buff) {
|
||||
// shrink the buffer
|
||||
if r.head == -1 {
|
||||
// nothing in the buffer, so just shrink it directly
|
||||
r.buff = r.buff[0:size]
|
||||
} else {
|
||||
newb := make([]interface{}, 0, size)
|
||||
// buffer has stuff in it, so save the most recent stuff...
|
||||
// start at HEAD-SIZE-1 and walk forwards
|
||||
for i := size - 1; i >= 0; i-- {
|
||||
idx := r.mod(r.head - i)
|
||||
newb = append(newb, r.buff[idx])
|
||||
}
|
||||
// reset head and tail to proper values
|
||||
r.head = len(newb) - 1
|
||||
r.tail = 0
|
||||
r.buff = newb
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// grow the buffer
|
||||
newb := make([]interface{}, size-len(r.buff))
|
||||
for i := range newb {
|
||||
newb[i] = nil
|
||||
}
|
||||
r.buff = append(r.buff, newb...)
|
||||
if r.head == -1 {
|
||||
// nothing in the buffer
|
||||
r.buff = append(r.buff, newb...)
|
||||
} else if r.head >= r.tail {
|
||||
// growing at the end is safe
|
||||
r.buff = append(r.buff, newb...)
|
||||
} else {
|
||||
// buffer has stuff that wraps around the end
|
||||
// have to rearrange the buffer so the contents are still in order
|
||||
part1 := make([]interface{}, len(r.buff[:r.head+1]))
|
||||
copy(part1, r.buff[:r.head+1])
|
||||
part2 := make([]interface{}, len(r.buff[r.tail:]))
|
||||
copy(part2, r.buff[r.tail:])
|
||||
r.buff = append(r.buff, newb...)
|
||||
newTail := r.mod(r.tail + len(newb))
|
||||
r.tail = newTail
|
||||
copy(r.buff[:r.head+1], part1)
|
||||
copy(r.buff[r.head+1:r.tail], newb)
|
||||
copy(r.buff[r.tail:], part2)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ github.com/42wim/go-gitter
|
|||
## explicit
|
||||
github.com/Baozisoftware/qrcode-terminal-go
|
||||
# github.com/Jeffail/gabs v1.4.0
|
||||
## explicit
|
||||
github.com/Jeffail/gabs
|
||||
# github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
||||
## explicit
|
||||
|
@ -27,8 +28,6 @@ github.com/Rhymen/go-whatsapp/binary/token
|
|||
github.com/Rhymen/go-whatsapp/crypto/cbc
|
||||
github.com/Rhymen/go-whatsapp/crypto/curve25519
|
||||
github.com/Rhymen/go-whatsapp/crypto/hkdf
|
||||
# github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210112200207-10ab4d695d60
|
||||
## explicit
|
||||
# github.com/SevereCloud/vksdk/v2 v2.9.0
|
||||
## explicit
|
||||
github.com/SevereCloud/vksdk/v2
|
||||
|
@ -82,6 +81,7 @@ github.com/google/gops/signal
|
|||
# github.com/google/uuid v1.1.2
|
||||
github.com/google/uuid
|
||||
# github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4
|
||||
## explicit
|
||||
github.com/gopackage/ddp
|
||||
# github.com/gorilla/schema v1.2.0
|
||||
## explicit
|
||||
|
@ -118,6 +118,9 @@ github.com/keybase/go-keybase-chat-bot/kbchat/types/chat1
|
|||
github.com/keybase/go-keybase-chat-bot/kbchat/types/gregor1
|
||||
github.com/keybase/go-keybase-chat-bot/kbchat/types/keybase1
|
||||
github.com/keybase/go-keybase-chat-bot/kbchat/types/stellar1
|
||||
# github.com/kyokomi/emoji/v2 v2.2.8
|
||||
## explicit
|
||||
github.com/kyokomi/emoji/v2
|
||||
# github.com/labstack/echo/v4 v4.2.1
|
||||
## explicit
|
||||
github.com/labstack/echo/v4
|
||||
|
@ -130,15 +133,12 @@ github.com/labstack/gommon/random
|
|||
# github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7
|
||||
## explicit
|
||||
github.com/lrstanley/girc
|
||||
# github.com/magefile/mage v1.10.0
|
||||
github.com/magefile/mage/mg
|
||||
github.com/magefile/mage/sh
|
||||
# github.com/magiconair/properties v1.8.1
|
||||
github.com/magiconair/properties
|
||||
# github.com/matrix-org/gomatrix v0.0.0-20200827122206-7dd5e2a05bcd
|
||||
# github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
|
||||
## explicit
|
||||
github.com/matrix-org/gomatrix
|
||||
# github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20201206215757-c1d86d75b9f8
|
||||
# github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d
|
||||
## explicit
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK/models
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK/realtime
|
||||
|
@ -146,9 +146,6 @@ github.com/matterbridge/Rocket.Chat.Go.SDK/rest
|
|||
# github.com/matterbridge/discordgo v0.21.2-0.20210201201054-fb39a175b4f7
|
||||
## explicit
|
||||
github.com/matterbridge/discordgo
|
||||
# github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||
## explicit
|
||||
github.com/matterbridge/emoji
|
||||
# github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050
|
||||
## explicit
|
||||
github.com/matterbridge/go-xmpp
|
||||
|
@ -222,7 +219,7 @@ github.com/pmezard/go-difflib/difflib
|
|||
github.com/rickb777/date/period
|
||||
# github.com/rickb777/plural v1.2.0
|
||||
github.com/rickb777/plural
|
||||
# github.com/rs/xid v1.2.1
|
||||
# github.com/rs/xid v1.3.0
|
||||
## explicit
|
||||
github.com/rs/xid
|
||||
# github.com/russross/blackfriday v1.6.0
|
||||
|
@ -238,7 +235,7 @@ github.com/shazow/rateio
|
|||
github.com/shazow/ssh-chat/internal/sanitize
|
||||
github.com/shazow/ssh-chat/sshd
|
||||
github.com/shazow/ssh-chat/sshd/terminal
|
||||
# github.com/sirupsen/logrus v1.8.0
|
||||
# github.com/sirupsen/logrus v1.8.1
|
||||
## explicit
|
||||
github.com/sirupsen/logrus
|
||||
# github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9
|
||||
|
@ -303,7 +300,7 @@ github.com/writeas/go-strip-markdown
|
|||
github.com/yaegashi/msgraph.go/beta
|
||||
github.com/yaegashi/msgraph.go/jsonx
|
||||
github.com/yaegashi/msgraph.go/msauth
|
||||
# github.com/zfjagann/golang-ring v0.0.0-20190304061218-d34796e0a6c2
|
||||
# github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
|
||||
## explicit
|
||||
github.com/zfjagann/golang-ring
|
||||
# go.uber.org/atomic v1.7.0
|
||||
|
@ -355,7 +352,7 @@ golang.org/x/net/http2/h2c
|
|||
golang.org/x/net/http2/hpack
|
||||
golang.org/x/net/idna
|
||||
golang.org/x/net/websocket
|
||||
# golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84
|
||||
# golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
## explicit
|
||||
golang.org/x/oauth2
|
||||
golang.org/x/oauth2/clientcredentials
|
||||
|
|
Loading…
Reference in New Issue