Привет, Хабр!

Если вы когда либо работали с JetBrains IDEs с разных компьютеров, вы могли сталкиваться с проблемой, что вам приходилось заново указывать настройки IDE (сочетания клавиш, подсветку синтаксиса, внешний вид, плагины и другие настройки).

До сих пор эту проблему частично решал встроенный плагин Settings Repository. Для того, чтобы, плагин синхронизировал настройки, необходимо самостоятельно создать Git репозиторий (на GitHub или другом сервисе) и указать его в IDE.

Очевидным минусом этого подхода является необходимость самостоятельно возиться с Git репозиторием. Не говоря уже о том, что, в случае использования публичного репозитория, ваши настройки могут быть доступны другим пользователям.

Для того, чтобы сделать процесс синхронизации настроек более удобным и безопасным, мы разрабатываем новый механизм, который частично опирается на Settings Repository, однако использует для хранения настроек репозиторий на стороне JetBrains. Доступ к этому репозиторию осуществляется посредством JetBrains Account (JBA).

Кроме более удобного способа хранения, новый механизм позволяет синхронизировать не только настройки, но и установленные плагины.

Что такое JetBrains Account

JetBrains Account можно использовать для управления лицензиями, доступа к форумам, блогам JetBrains и репозиторию плагинов. Подробнее о том как работает JetBrains Account можно узнать здесь (на английском).

Доступ к плагину

Новый плагин называется IDE Settings Sync и совместим начиная с версии 2017.2.1. Учитывая раннюю стадию готовности плагина, доступ к нему можно получить пока только по приглашениям.

Если у вас уже есть приглашение, вы можете пригласить ваших коллег и друзей через форму на сайте JetBrains Account.

Если у вас нет приглашения, вы можете попросить его отправив письмо на idea-cloudconfig@jetbrains.com. При этом, письмо должно быть отправлено с почтового ящика, привязанного к вашему JetBrains Account.

Если у вас нет JetBrains Account, его можно легко создать на сайте JetBrains Account. При создании JetBrains Account, мы рекомендуем указывать тот же почтовый ящик, который указан в данных ваших купленных лицензий.

Ограничения плагина на данный момент

Плагин доступен только для платных продуктов (IntelliJ IDEA Ultimate, PhpStorm, PyCharm, CLion, RubyMine, Rider, и т.п.)
Плагин пока не работает вместе с License Server (мы работаем над этим).

Чтобы плагин заработал, необходимо

1. Получить письмо с приглашением



2. Установить плагин

3. Авторизоваться в IDE (или Toolbox App) с помощью JetBrains Account



4. Включить синхронизацию



5. Отправить приглашение хорошему другу



Обратная связь

Учитывая, что плагин все еще находится в активной разработке, возможны ошибки. В случае, если вы столкнетесь с проблемами, пишите нам о них комментариях на странице плагина или напрямую в трекер.

Я и авторы плагина будем рады ответить на вопросы.

Программируйте с удовольствием!

Комментарии (36)


  1. Borz
    14.08.2017 23:25

    а почему не стали расширять возможности старого плагина в виде переключателя между местом хранения настроек?
    тем более, что в старом плагине можно было комбинировать репозитарии личные с рабочими для настроек. А в текущем, как я понял, только личные настройки, которые даже посмотреть нельзя или подправить в VCS


    1. stalk
      14.08.2017 23:53
      +1

      Новый плагин это и есть расширение старого. IDE Settings Sync построен на одном движке с Settings Repository. Но в новом плагине упор делался на usability, поэтому было принято решение написать отдельный UI и не путать пользователей, которые уже используют Settings Repository. Также в новом плагине есть интеграция с JetBrains Toolbox App. Вариант, к которому мы стремимся, это максимально упростить жизнь пользователя: поставил OS, поставил Toolbox App, залогинился и всё настроено.


  1. pmcode
    15.08.2017 06:42
    +1

    Новый плагин умеет синхронизировать настройки выборочно? Я пытался использовать Settings Repository для синхронизации м/у домашней и рабочей машиной, но он таскает за собой настройки прокси (есть на работе, нет дома), каталоги, например, Maven и прочие дистроспецифичные штуки, хотя от него всего-то требовалось зазеркалить Live Templates. Плюс, работает не всегда. Плюс, пару раз тупо сломал настройки. Я сначала думал что ну не может официальный плагин от JB такой низкий рейтинг, а нет, все правильно.


    1. stalk
      15.08.2017 12:35

      Выборочная синхронизация сделана для плагинов. Сейчас думаем над тем для каких опций её ещё сделать. С одной стороны хочется оставить UI удобным и понятным, с другой дать пользователям то, что им нужно. Какие сеттинги для вас нуждаются в подобной кастомизации?


  1. kiff86
    15.08.2017 07:59

    Тоже соглашусь, что выборочная синхронизация была бы удобна. (Привет от прокси на работе). А также интересно как они синхронизируются: у меня есть Настройки на работе и дома. Что будет затерто в итоге?


  1. sacred
    15.08.2017 09:09

    пытаюсь поставить в аппкод через ручную установку плагина и выбора зип архива. получаю такое. я что-то делаю не так?

    image


    1. andreycheptsov Автор
      15.08.2017 09:11

      Проверьте, что у вас Ultimate 2017.2.1 или выше.


      1. sacred
        15.08.2017 12:13

        самый последний стабильный AppCode 2017.2. Новее вроде как ничего нет.


      1. sacred
        15.08.2017 12:29

        а, нашел AppCode 2017.2.1 eap


      1. sacred
        15.08.2017 12:44

        Установилось нормаьно, настроилось. на второй запуск вот такое

        Проблема при запуске
        Internal error. Please report to http://jb.gg/ide/critical-startup-errors
        
        java.lang.RuntimeException: com.intellij.ide.plugins.PluginManager$StartupAbortedException: Fatal error initializing 'com.intellij.openapi.keymap.KeymapManager'
            at com.intellij.idea.IdeaApplication.run(IdeaApplication.java:210)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at com.intellij.idea.MainImpl$1$1.a(MainImpl.java:64)
            at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
            at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:762)
            at java.awt.EventQueue.access$500(EventQueue.java:98)
            at java.awt.EventQueue$3.run(EventQueue.java:715)
            at java.awt.EventQueue$3.run(EventQueue.java:709)
            at java.security.AccessController.doPrivileged(Native Method)
            at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
            at java.awt.EventQueue.dispatchEvent(EventQueue.java:732)
            at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:345)
            at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
            at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
            at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
            at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
            at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
        Caused by: com.intellij.ide.plugins.PluginManager$StartupAbortedException: Fatal error initializing 'com.intellij.openapi.keymap.KeymapManager'
            at com.intellij.ide.plugins.PluginManager.handleComponentError(PluginManager.java:258)
            at com.intellij.openapi.components.impl.PlatformComponentManagerImpl.handleInitComponentError(PlatformComponentManagerImpl.java:43)
            at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:510)
            at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:239)
            at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:206)
            at org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)
            at org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:114)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getConstructorArguments(CachingConstructorInjectionComponentAdapter.java:129)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.doGetComponentInstance(CachingConstructorInjectionComponentAdapter.java:100)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.instantiateGuarded(CachingConstructorInjectionComponentAdapter.java:80)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getComponentInstance(CachingConstructorInjectionComponentAdapter.java:63)
            at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:469)
            at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:239)
            at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:206)
            at org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)
            at org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:114)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getConstructorArguments(CachingConstructorInjectionComponentAdapter.java:129)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.doGetComponentInstance(CachingConstructorInjectionComponentAdapter.java:100)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.instantiateGuarded(CachingConstructorInjectionComponentAdapter.java:80)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getComponentInstance(CachingConstructorInjectionComponentAdapter.java:63)
            at com.intellij.openapi.components.impl.ServiceManagerImpl$MyComponentAdapter.getComponentInstance(ServiceManagerImpl.java:220)
            at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:239)
            at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:206)
            at org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)
            at org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:114)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getConstructorArguments(CachingConstructorInjectionComponentAdapter.java:129)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.doGetComponentInstance(CachingConstructorInjectionComponentAdapter.java:100)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.instantiateGuarded(CachingConstructorInjectionComponentAdapter.java:80)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getComponentInstance(CachingConstructorInjectionComponentAdapter.java:63)
            at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:469)
            at com.intellij.openapi.components.impl.ComponentManagerImpl.createComponents(ComponentManagerImpl.java:118)
            at com.intellij.openapi.application.impl.ApplicationImpl.a(ApplicationImpl.java:475)
            at com.intellij.openapi.progress.impl.CoreProgressManager.a(CoreProgressManager.java:170)
            at com.intellij.openapi.progress.impl.CoreProgressManager.a(CoreProgressManager.java:548)
            at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:493)
            at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:94)
            at com.intellij.openapi.progress.impl.CoreProgressManager.runProcess(CoreProgressManager.java:157)
            at com.intellij.openapi.application.impl.ApplicationImpl.createComponents(ApplicationImpl.java:482)
            at com.intellij.openapi.components.impl.ComponentManagerImpl.init(ComponentManagerImpl.java:102)
            at com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:434)
            at com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:420)
            at com.intellij.idea.IdeaApplication.run(IdeaApplication.java:203)
            ... 20 more
        Caused by: java.lang.NoClassDefFoundError: com/intellij/util/io/PathKt$sam$Filter$i$855e4f15
            at com.intellij.cloudConfig.CloudConfigStreamProvider.processChildren(CloudConfigStreamProvider.kt:128)
            at com.intellij.configurationStore.CompoundStreamProvider.processChildren(CompoundStreamProvider.kt:22)
            at com.intellij.configurationStore.SchemeManagerImpl.loadSchemes(SchemeManagerImpl.kt:291)
            at com.intellij.openapi.keymap.impl.KeymapManagerImpl.<init>(KeymapManagerImpl.kt:81)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
            at org.picocontainer.defaults.InstantiatingComponentAdapter.newInstance(InstantiatingComponentAdapter.java:193)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.doGetComponentInstance(CachingConstructorInjectionComponentAdapter.java:103)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.instantiateGuarded(CachingConstructorInjectionComponentAdapter.java:80)
            at com.intellij.util.pico.CachingConstructorInjectionComponentAdapter.getComponentInstance(CachingConstructorInjectionComponentAdapter.java:63)
            at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:469)
            ... 59 more
        Caused by: java.lang.ClassNotFoundException: com.intellij.util.io.PathKt$sam$Filter$i$855e4f15 PluginClassLoader[com.intellij.CloudConfig, 172.3769.2] com.intellij.ide.plugins.cl.PluginClassLoader@3b6c2899
            at com.intellij.ide.plugins.cl.PluginClassLoader.loadClass(PluginClassLoader.java:65)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
            ... 72 more
        


  1. igor_sky
    15.08.2017 09:09

    Вы бы решили проблему VCS для папки проекта, папку с проектом .idea проще добавить в игнор чем синхронизировать с командой, а решить то проблему можно довольно просто, сделайте подпапку local которую нужно игнорировать а остальное пусть лежит в VCS, а сейчас там разберись какой файл нужен, какой не нужен, и в синхронизацию уходят локальные пути и еще кучу всего что не нужно шейрить, в целом удивительно что до сих пор проекты любой Jetbrains IDE невозможно юзабельно поддерживать в репозитории.


    1. e_Hector
      15.08.2017 09:54

      но ведь для этого давно придумали системы сборки


    1. Borz
      15.08.2017 11:55

      лично мне хватает этого в .gitignore:


      .idea/*
      !.idea/fileTemplates/
      !.idea/contracts/
      !.idea/encodings.xml
      !.idea/compiler.xml
      !.idea/vcs.xml
      !.idea/dictionaries/
      .idea/fileTemplates/includes/
      *.iml
      *.ipr


  1. zein
    15.08.2017 10:05
    +1

    Теперь будет 2 плагина которые невозможно нормально использовать? Без выборочной синхронизации, нормальной поддержки $PROJECT_DIR$ везде, синхронизацией настроек конкретного проекта от них толку немного.


  1. Caravus
    15.08.2017 11:41

    Довольно странный способ потестировать плагин — запрашивать инвайт через почту. Зачем это нужно?


    1. stalk
      15.08.2017 12:44

      При данном подходе тестируется не функционал плагина, а нагрузка на серверную часть. При бета-тестировании хочется вывести серверную часть под нагрузку плавно. Система предполагает, что участники будут делиться инвайтами между собой


      1. Caravus
        15.08.2017 12:47

        Ну так сделайте плагин доступным только EAP, например, но автоматом, без всяких там «отправьте на почту, мы вам не будем отвечать». Ну ок, если прям хочется что-то такое — сделайте кнопку на сайте в личном кабинете «получить доступ» с автоматической выдачей инвайтов до Х штук.


  1. tmin10
    15.08.2017 11:59

    Подскажите, а планируется ли работа плагина синхронизации в том случае, если используется сервер для получения лицензий?
    P.S. Прочитал заметку в статье про это, прошу прощения…


  1. bm13kk
    15.08.2017 12:34

    Синхронизировать проектные настройки гораздо важнее.


    1. stalk
      15.08.2017 12:40

      В IntelliJ этот механизм работает через VCS. Ваши проектные настройки лежат в .idea вместе с сорцами.