From a5cb87a796abcaffa052ce90d96c16df4d5acb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 11:41:45 +0800 Subject: [PATCH 01/61] supplement portuguese brazil translation Fix #33672 --- app/assets/javascripts/locale/pt_BR/app.js | 2 +- locale/pt_BR/gitlab.po | 1013 ++++++++++++++++++-- 2 files changed, 946 insertions(+), 69 deletions(-) diff --git a/app/assets/javascripts/locale/pt_BR/app.js b/app/assets/javascripts/locale/pt_BR/app.js index f2eed3da064..957b0c56333 100644 --- a/app/assets/javascripts/locale/pt_BR/app.js +++ b/app/assets/javascripts/locale/pt_BR/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-05 03:29-0400","Last-Translator":"Alexandre Alencar ","Language-Team":"Portuguese (Brazil)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"ByAuthor|by":["por"],"Commit":["Commit","Commits"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Tarefa"],"CycleAnalyticsStage|Plan":["Plano"],"CycleAnalyticsStage|Production":["Produção"],"CycleAnalyticsStage|Review":["Revisão"],"CycleAnalyticsStage|Staging":["Homologação"],"CycleAnalyticsStage|Test":["Teste"],"Deploy":["Implantação","Implantações"],"FirstPushedBy|First":["Primeiro"],"FirstPushedBy|pushed by":["publicado por"],"From issue creation until deploy to production":["Da criação de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da incorporação do merge request até a implantação em produção"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"Last %d day":["Último %d dia","Últimos %d dias"],"Limited to showing %d event at most":["Limitado a mostrar %d evento no máximo","Limitado a mostrar %d eventos no máximo"],"Median":["Mediana"],"New Issue":["Nova Tarefa","Novas Tarefas"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"OpenedNDaysAgo|Opened":["Aberto"],"Pipeline Health":["Saúde da Pipeline"],"ProjectLifecycle|Stage":["Etapa"],"Read more":["Ler mais"],"Related Commits":["Commits Relacionados"],"Related Deployed Jobs":["Jobs Relacionados Incorporados"],"Related Issues":["Tarefas Relacionadas"],"Related Jobs":["Jobs Relacionados"],"Related Merge Requests":["Merge Requests Relacionados"],"Related Merged Requests":["Merge Requests Relacionados"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["O estágio de codificação mostra o tempo desde o primeiro commit até a criação do merge request. \\nOs dados serão automaticamente adicionados aqui uma vez que você tenha criado seu primeiro merge request."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para esse estágio."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["O estágio em questão mostra o tempo que leva desde a criação de uma tarefa até a sua assinatura para um milestone, ou a sua adição para a lista no seu Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["A fase de planejamento mostra o tempo do passo anterior até empurrar o seu primeiro commit. Este tempo será adicionado automaticamente assim que você realizar seu primeiro commit."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["O estágio de produção mostra o tempo total que leva entre criar uma tarefa e implantar o código na produção. Os dados serão adicionados automaticamente até que você complete todo o ciclo de produção."],"The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.":["A etapa de revisão mostra o tempo de criação de um merge request até que o merge seja feito. Os dados serão automaticamente adicionados depois que você fizer seu primeiro merge request."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["O estágio de estágio mostra o tempo entre a fusão do MR e o código de implantação para o ambiente de produção. Os dados serão automaticamente adicionados depois de implantar na produção pela primeira vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["A fase de teste mostra o tempo que o GitLab CI leva para executar cada pipeline para o merge request relacionado. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário para cada entrada de dados reunida por essa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6."],"Time before an issue gets scheduled":["Tempo até que uma tarefa seja planejada"],"Time before an issue starts implementation":["Tempo até que uma tarefa comece a ser implementada"],"Time between merge request creation and merge/close":["Tempo entre a criação do merge request e o merge/fechamento"],"Time until first merge request":["Tempo até o primeiro merge request"],"Time|hr":["h","hs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Não temos dados suficientes para mostrar esta fase."],"You need permission.":["Você precisa de permissão."],"day":["dia","dias"]}}}; \ No newline at end of file +var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-12 19:29-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-13 04:05-0400","Last-Translator":"Bruno Guimarães ","Language-Team":"Portuguese (Brazil) (https://translate.zanata.org/project/view/GitLab)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} fez commit %{commit_timeago}"],"About auto deploy":["Sobre a implantação automática"],"Active":["Ativo"],"Activity":["Atividade"],"Add Changelog":["Adicionar registro de mudanças"],"Add Contribution guide":["Adicionar Guia de contribuição"],"Add License":["Adicionar Licença"],"Add an SSH key to your profile to pull or push via SSH.":["Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH."],"Add new directory":["Adicionar novo diretório"],"Archived project! Repository is read-only":["Projeto arquivado! O repositório é somente leitura"],"Are you sure you want to delete this pipeline schedule?":["Tem certeza que deseja excluir este agendamento de pipeline?"],"Attach a file by drag & drop or %{upload_link}":["Para anexar arquivo, arraste e solte ou %{upload_link}"],"Branch":["Branch","Branches"],"Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":["O branch %{branch_name} foi criado. Para configurar a auto implantação, selecione um modelo de Yaml do GitLab CI e registre suas mudanças. \\n%{link_to_autodeploy_doc}"],"Branches":["Branches"],"Browse files":["Navegar pelos arquivos"],"ByAuthor|by":["ByAuthor|por"],"CI configuration":["Configuração da Integração Contínua"],"Cancel":["Cancelar"],"ChangeTypeActionLabel|Pick into branch":["ChangeTypeActionLabel|Pick para um branch"],"ChangeTypeActionLabel|Revert in branch":["ChangeTypeActionLabel|Reverter no branch"],"ChangeTypeAction|Cherry-pick":["ChangeTypeAction|Cherry-pick"],"ChangeType|commit":["ChangeType|commit"],"ChangeType|merge request":["ChangeType|merge request"],"Changelog":["Registro de mudanças"],"Charts":["Gráficos"],"Cherry-pick this commit":["Cherry-pick esse commit"],"Cherry-pick this merge-request":["Cherry-pick esse merge-request"],"CiStatusLabel|canceled":["CiStatusLabel|cancelado"],"CiStatusLabel|created":["CiStatusLabel|criado"],"CiStatusLabel|failed":["CiStatusLabel|falhou"],"CiStatusLabel|manual action":["CiStatusLabel|ação manual"],"CiStatusLabel|passed":["CiStatusLabel|passou"],"CiStatusLabel|passed with warnings":["CiStatusLabel|passou com avisos"],"CiStatusLabel|pending":["CiStatusLabel|pendente"],"CiStatusLabel|skipped":["CiStatusLabel|ignorado"],"CiStatusLabel|waiting for manual action":["CiStatusLabel|aguardando ação manual"],"CiStatusText|blocked":["CiStatusText|bloqueado"],"CiStatusText|canceled":["CiStatusText|cancelado"],"CiStatusText|created":["CiStatusText|criado"],"CiStatusText|failed":["CiStatusText|falhou"],"CiStatusText|manual":["CiStatusText|manual"],"CiStatusText|passed":["CiStatusText|passou"],"CiStatusText|pending":["CiStatusText|pendente"],"CiStatusText|skipped":["CiStatusText|ignorado"],"CiStatus|running":["CiStatus|executando"],"Commit":["Conjunto de mudanças","Conjuntos de mudanças"],"Commit message":["Mensagem do conjunto de mudanças"],"CommitMessage|Add %{file_name}":["CommitMessage|Adicionar %{file_name}"],"Commits":["Conjuntos de mudanças"],"Commits|History":["Commits|Histórico"],"Committed by":["Entregue por"],"Compare":["Comparar"],"Contribution guide":["Guia de contribuição"],"Contributors":["Contribuidores"],"Copy URL to clipboard":["Copiar URL para área de transferência"],"Copy commit SHA to clipboard":["Copiar SHA do conjunto de mudanças para a área de transferência"],"Create New Directory":["Criar Novo Diretório"],"Create directory":["Criar diretório"],"Create empty bare repository":["Criar repositório centralizado vazio"],"Create merge request":["Criar solicitação de incorporação"],"Create new...":["Criar novo..."],"CreateNewFork|Fork":["CreateNewFork|Fork"],"CreateTag|Tag":["CreateTag|Tag"],"Cron Timezone":["Fuso horário do cron"],"Cron syntax":["Sintaxe do cron"],"Custom":["Personalizar"],"Custom notification events":["Eventos de notificação personalizados"],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":["Níveis de notificação personalizados são equivalentes a níveis de participação. Com níveis de notificação personalizados você também será notificado sobre eventos selecionados. Para mais informações, visite %{notification_link}."],"Cycle Analytics":["Análise de Ciclo"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["CycleAnalyticsStage|Código"],"CycleAnalyticsStage|Issue":["CycleAnalyticsStage|Relato"],"CycleAnalyticsStage|Plan":["CycleAnalyticsStage|Plano"],"CycleAnalyticsStage|Production":["CycleAnalyticsStage|Produção"],"CycleAnalyticsStage|Review":["CycleAnalyticsStage|Revisão"],"CycleAnalyticsStage|Staging":["CycleAnalyticsStage|Homologação"],"CycleAnalyticsStage|Test":["CycleAnalyticsStage|Teste"],"Define a custom pattern with cron syntax":["Defina um padrão personalizado utilizando a sintaxe do cron"],"Delete":["Excluir"],"Deploy":["Implantação","Implantações"],"Description":["Descrição"],"Directory name":["Nome do diretório"],"Don't show again":["Não exibir novamente"],"Download":["Baixar"],"Download tar":["Baixar tar"],"Download tar.bz2":["Baixar tar.bz2"],"Download tar.gz":["Baixar tar.gz"],"Download zip":["Baixar zip"],"DownloadArtifacts|Download":["DownloadArtifacts|Baixar"],"DownloadCommit|Email Patches":["DownloadCommit|Email com as mudanças"],"DownloadCommit|Plain Diff":["DownloadCommit|Arquivo de texto com as mudanças"],"DownloadSource|Download":["DownloadSource|Baixar"],"Edit":["Alterar"],"Edit Pipeline Schedule %{id}":["Alterar Agendamento do Pipeline %{id}"],"Every day (at 4:00am)":["Todos os dias (às 4:00)"],"Every month (on the 1st at 4:00am)":["Todos os meses (no dia primeiro às 4:00)"],"Every week (Sundays at 4:00am)":["Toda semana (domingos às 4:00)"],"Failed to change the owner":["Erro ao alterar o proprietário"],"Failed to remove the pipeline schedule":["Erro ao excluir o agendamento do pipeline"],"Files":["Arquivos"],"Find by path":["Localizar por caminho"],"Find file":["Localizar arquivo"],"FirstPushedBy|First":["FirstPushedBy|Primeiro"],"FirstPushedBy|pushed by":["FirstPushedBy|publicado por"],"Fork":["Bifurcação","Bifurcações"],"ForkedFromProjectPath|Forked from":["ForkedFromProjectPath|Forked de"],"From issue creation until deploy to production":["Da abertura de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da aceitação da solicitação de incorporação até a implantação em produção"],"Go to your fork":["Ir para sua bifurcação"],"GoToYourFork|Fork":["GoToYourFork|Bifurcação"],"Home":["Início"],"Housekeeping successfully started":["Manutenção iniciada com sucesso"],"Import repository":["Importar repositório"],"Interval Pattern":["Padrão de intervalo"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"LFSStatus|Disabled":["LFSStatus|Desabilitado"],"LFSStatus|Enabled":["LFSStatus|Habilitado"],"Last %d day":["Último %d dia","Últimos %d dias"],"Last Pipeline":["Último Pipeline"],"Last Update":["Última Atualização"],"Last commit":["Último conjunto de mudanças"],"Learn more in the":["Saiba mais em"],"Leave group":["Sair do grupo"],"Leave project":["Sair do projeto"],"Limited to showing %d event at most":["Limitado a mostrar %d evento, no máximo","Limitado a mostrar %d eventos, no máximo"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":["MissingSSHKeyWarningLink|adicione uma chave SSH"],"New Issue":["Novo Relato","Novos Relatos"],"New Pipeline Schedule":["Novo Agendamento de Pipeline"],"New branch":["Nova ramificação"],"New directory":["Novo diretório"],"New file":["Novo arquivo"],"New issue":["Novo relato"],"New merge request":["Nova solicitação de incorporação"],"New schedule":["Novo agendamento"],"New snippet":["Novo snippet"],"New tag":["Nova tag"],"No repository":["Nenhum repositório"],"No schedules":["Nenhum agendamento"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"Notification events":["Eventos de notificação"],"NotificationEvent|Close issue":["NotificationEvent|Fechar relato"],"NotificationEvent|Close merge request":["NotificationEvent|Fechar solicitação de incorporação"],"NotificationEvent|Failed pipeline":["NotificationEvent|Falha no pipeline"],"NotificationEvent|Merge merge request":["NotificationEvent|Aceitar merge request"],"NotificationEvent|New issue":["NotificationEvent|Novo relato"],"NotificationEvent|New merge request":["NotificationEvent|Novo merge request"],"NotificationEvent|New note":["NotificationEvent|Novo comentário"],"NotificationEvent|Reassign issue":["NotificationEvent|Reatribuir relato"],"NotificationEvent|Reassign merge request":["NotificationEvent|Reatribuir merge request"],"NotificationEvent|Reopen issue":["NotificationEvent|Reabrir relato"],"NotificationEvent|Successful pipeline":["NotificationEvent|Pipeline bem sucedido"],"NotificationLevel|Custom":["NotificationLevel|Personalizar"],"NotificationLevel|Disabled":["NotificationLevel|Desabilitado"],"NotificationLevel|Global":["NotificationLevel|Global"],"NotificationLevel|On mention":["NotificationLevel|Quando mencionado"],"NotificationLevel|Participate":["NotificationLevel|Participar"],"NotificationLevel|Watch":["NotificationLevel|Observar"],"OfSearchInADropdown|Filter":["OfSearchInADropdown|Filtrar"],"OpenedNDaysAgo|Opened":["OpenedNDaysAgo|Aberto"],"Options":["Opções"],"Owner":["Proprietário"],"Pipeline":["Pipeline"],"Pipeline Health":["Saúde da Pipeline"],"Pipeline Schedule":["Agendamento da Pipeline"],"Pipeline Schedules":["Agendamentos da Pipeline"],"PipelineSchedules|Activated":["PipelineSchedules|Ativado"],"PipelineSchedules|Active":["PipelineSchedules|Ativo"],"PipelineSchedules|All":["PipelineSchedules|Todos"],"PipelineSchedules|Inactive":["PipelineSchedules|Inativo"],"PipelineSchedules|Next Run":["PipelineSchedules|Próxima Execução"],"PipelineSchedules|None":["PipelineSchedules|Nenhum"],"PipelineSchedules|Provide a short description for this pipeline":["PipelineSchedules|Digite uma descrição curta para esta pipeline"],"PipelineSchedules|Take ownership":["PipelineSchedules|Tornar-se proprietário"],"PipelineSchedules|Target":["PipelineSchedules|Destino"],"Project '%{project_name}' queued for deletion.":["Projeto'%{project_name}' marcado para exclusão."],"Project '%{project_name}' was successfully created.":["Projeto '%{project_name}' criado com sucesso."],"Project '%{project_name}' was successfully updated.":["Projeto '%{project_name}' atualizado com sucesso."],"Project '%{project_name}' will be deleted.":["Projeto '%{project_name}' será excluído."],"Project access must be granted explicitly to each user.":["Acesso ao projeto deve ser concedido explicitamente para cada usuário."],"Project export could not be deleted.":["A exportação do projeto não pôde ser excluída."],"Project export has been deleted.":["Exportação do projeto excluída."],"Project export link has expired. Please generate a new export from your project settings.":["O link para a exportação do projeto expirou. Favor gerar uma nova exportação a partir das configurações do projeto."],"Project export started. A download link will be sent by email.":["Exportação do projeto iniciada. Um link para baixá-la será enviado por email."],"Project home":["Página inicial do projeto"],"ProjectFeature|Disabled":["ProjectFeature|Desabilitado"],"ProjectFeature|Everyone with access":["ProjectFeature|Todos que possuem acesso"],"ProjectFeature|Only team members":["ProjectFeature|Apenas membros do time"],"ProjectFileTree|Name":["ProjectFileTree|Nome"],"ProjectLastActivity|Never":["ProjectLastActivity|Nunca"],"ProjectLifecycle|Stage":["PipelineSchedules|Etapa"],"ProjectNetworkGraph|Graph":["ProjectNetworkGraph|Árvore"],"Read more":["Leia mais"],"Readme":["Leia-me"],"RefSwitcher|Branches":["RefSwitcher|Ramificações"],"RefSwitcher|Tags":["RefSwitcher|Tags"],"Related Commits":["Conjuntos de Mudanças Relacionados"],"Related Deployed Jobs":["Tarefas Implantadas Relacionadas"],"Related Issues":["Relatos Relacionados"],"Related Jobs":["Tarefas Relacionadas"],"Related Merge Requests":["Solicitações de Incorporação Relacionadas"],"Related Merged Requests":["Solicitações de Incorporação Aceitas Relacionadas"],"Remind later":["Lembrar mais tarde"],"Remove project":["Remover projeto"],"Request Access":["Solicitar acesso"],"Revert this commit":["Reverter este conjunto de mudanças"],"Revert this merge-request":["Reverter esta solicitação de incorporação"],"Save pipeline schedule":["Salvar agendamento da pipeline"],"Schedule a new pipeline":["Agendar nova pipeline"],"Scheduling Pipelines":["Agendando pipelines"],"Search branches and tags":["Procurar ramificações e tags"],"Select Archive Format":["Selecionar Formato do Arquivo"],"Select a timezone":["Selecionar fuso horário"],"Select target branch":["Selecionar ramificação de destino"],"Set a password on your account to pull or push via %{protocol}":["Defina uma senha para sua conta para aceitar ou entregar código via %{protocol}"],"Set up CI":["Configurar CI"],"Set up Koding":["Configurar Koding"],"Set up auto deploy":["Configurar auto implantação"],"SetPasswordToCloneLink|set a password":["SetPasswordToCloneLink|defina uma senha"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":["Código-fonte"],"StarProject|Star":["StarProject|Marcar"],"Start a new merge request with these changes":["Criar uma nova solicitação de incorporação com estas mudanças"],"Switch branch/tag":["Trocar ramificação/tag"],"Tag":["Tag","Tags"],"Tags":["Tags"],"Target Branch":["Ramificação de destino"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["A etapa de codificação mostra o tempo desde a entrega do primeiro conjunto de mudanças até a criação da solicitação de incorporação. Os dados serão automaticamente adicionados aqui desde o momento de criação da solicitação de incorporação."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para essa etapa."],"The fork relationship has been removed.":["O relacionamento como fork foi removido."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["A etapa de relatos mostra o tempo que leva desde a criação de um relato até sua atribuição a um marco, ou sua adição a uma lista no seu Quadro de Relatos. Comece a criar relatos para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":["O agendamento de pipeline executa pipelines no futuro, repetidamente, para ramificações ou tags específicas. Essas pipelines agendadas terão acesso limitado ao projeto baseado no seu usuário associado."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["A etapa de planejamento mostra o tempo do passo anterior até a publicação de seu primeiro conjunto de mudanças. Este tempo será adicionado automaticamente assim que você enviar seu primeiro conjunto de mudanças."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["A etapa de produção mostra o tempo total que leva entre criar um relato e implantar o código em produção. Os dados serão adicionados automaticamente assim que você completar todo o ciclo de produção."],"The project can be accessed by any logged in user.":["O projeto pode ser acessado por qualquer usuário autenticado."],"The project can be accessed without any authentication.":["O projeto pode ser acessado sem a necessidade de autenticação."],"The repository for this project does not exist.":["O repositório para este projeto não existe."],"The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.":["A etapa de revisão mostra o tempo de criação de uma solicitação de incorporação até sua aceitação. Os dados serão automaticamente adicionados depois que sua primeira solicitação de incorporação for aceita."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["A etapa de homologação mostra o tempo entre o aceite da solicitação de incorporação e a implantação do código no ambiente de produção. Os dados serão automaticamente adicionados depois que você implantar em produção pela primeira vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["A etapa de testes mostra o tempo que o GitLab CI leva para executar cada pipeline para a solicitação de incorporação associada. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário por cada entrada de dados reunida por essa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":["Isto significa que você não pode entregar código até que crie um repositório vazio ou importe um existente."],"Time before an issue gets scheduled":["Tempo até que um relato seja agendado"],"Time before an issue starts implementation":["Tempo até que um relato comece a ser implementado"],"Time between merge request creation and merge/close":["Tempo entre a criação da solicitação de incorporação e a aceitação/fechamento"],"Time until first merge request":["Tempo até a primeira solicitação de incorporação"],"Timeago|%s days ago":["Timeago|há %s dias"],"Timeago|%s days remaining":["Timeago|%s dias restantes"],"Timeago|%s hours remaining":["Timeago|%s horas restantes"],"Timeago|%s minutes ago":["Timeago|há %s minutos"],"Timeago|%s minutes remaining":["Timeago|%s minutos restantes"],"Timeago|%s months ago":["Timeago|há %s meses"],"Timeago|%s months remaining":["Timeago|%s meses restantes"],"Timeago|%s seconds remaining":["Timeago|%s segundos restantes"],"Timeago|%s weeks ago":["Timeago|há %s semanas"],"Timeago|%s weeks remaining":["Timeago|%s semanas restantes"],"Timeago|%s years ago":["Timeago|há %s anos"],"Timeago|%s years remaining":["Timeago|%s anos restantes"],"Timeago|1 day remaining":["Timeago|1 dia restante"],"Timeago|1 hour remaining":["Timeago|1 hora restante"],"Timeago|1 minute remaining":["Timeago|1 minuto restante"],"Timeago|1 month remaining":["Timeago|1 mês restante"],"Timeago|1 week remaining":["Timeago|1 semana restante"],"Timeago|1 year remaining":["Timeago|1 ano restante"],"Timeago|Past due":["Timeago|Venceu"],"Timeago|a day ago":["Timeago|há um dia"],"Timeago|a month ago":["Timeago|há um mês"],"Timeago|a week ago":["Timeago|há uma semana"],"Timeago|a while":["Timeago|há algum tempo"],"Timeago|a year ago":["Timeago|há um ano"],"Timeago|about %s hours ago":["Timeago|há cerca de %s horas"],"Timeago|about a minute ago":["Timeago|há cerca de um minuto"],"Timeago|about an hour ago":["Timeago|há cerca de uma hora"],"Timeago|in %s days":["Timeago|em %s dias"],"Timeago|in %s hours":["Timeago|em %s horas"],"Timeago|in %s minutes":["Timeago|em %s minutos"],"Timeago|in %s months":["Timeago|em %s meses"],"Timeago|in %s seconds":["Timeago|em %s segundos"],"Timeago|in %s weeks":["Timeago|em %s semanas"],"Timeago|in %s years":["Timeago|em %s anos"],"Timeago|in 1 day":["Timeago|em 1 dia"],"Timeago|in 1 hour":["Timeago|em 1 hora"],"Timeago|in 1 minute":["Timeago|em 1 minuto"],"Timeago|in 1 month":["Timeago|em 1 mês"],"Timeago|in 1 week":["Timeago|em 1 semana"],"Timeago|in 1 year":["Timeago|em 1 ano"],"Timeago|less than a minute ago":["Timeago|há menos de um minuto"],"Time|hr":["Time|h","Time|hs"],"Time|min":["Time|min","Time|mins"],"Time|s":["Time|s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Unstar":["Desmarcar"],"Upload New File":["Enviar Novo Arquivo"],"Upload file":["Enviar arquivo"],"Use your global notification setting":["Utilizar configuração de notificação global"],"VisibilityLevel|Internal":["VisibilityLevel|Interno"],"VisibilityLevel|Private":["VisibilityLevel|Privado"],"VisibilityLevel|Public":["VisibilityLevel|Público"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Esta etapa não possui dados suficientes para exibição."],"Withdraw Access Request":["Remover Requisição de Acesso"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Você irá remover %{project_name_with_namespace}.\\nO projeto removido NÃO PODE ser restaurado!\\nTem certeza ABSOLUTA?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Você ira remover o relacionamento de fork com o projeto original %{forked_from_project}. Tem certeza ABSOLUTA?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Você irá transferir %{project_name_with_namespace} para outro proprietário. Tem certeza ABSOLUTA?"],"You can only add files when you are on a branch":["Você somente pode adicionar arquivos quando estiver em um branch"],"You must sign in to star a project":["Você deve estar autenticado para marcar um projeto"],"You need permission.":["Você precisa de permissão."],"You will not get any notifications via email":["Você não será notificado por email"],"You will only receive notifications for the events you choose":["Você será notificado apenas sobre eventos selecionados"],"You will only receive notifications for threads you have participated in":["Você será notificado apenas sobre tópicos nos quais participou"],"You will receive notifications for any activity":["Você será notificado sobre qualquer atividade"],"You will receive notifications only for comments in which you were @mentioned":["Você será notificado apenas sobre comentários que te @mencionam"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["Você não poderá fazer pull ou push via %{protocol} até que %{set_password_link} para sua conta"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["Você não conseguirá fazer pull ou push no projeto via SSH até que adicione %{add_ssh_key_link} ao seu perfil"],"Your name":["Seu nome"],"day":["dia","dias"],"notification emails":["emails de notificação"],"parent":["pai","pais"],"pipeline schedules documentation":["documentação do agendamento de pipelines"],"with stage":["com a etapa","com as etapas"]}}}; \ No newline at end of file diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 5ad41f92b64..a10da077fd2 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,28 +1,248 @@ # Alexandre Alencar , 2017. #zanata +# Bruno Guimarães , 2017. #zanata # Fabio Beneditto , 2017. #zanata -# Leandro Nunes dos Santos , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-05-04 19:24-0500\n" +"POT-Creation-Date: 2017-06-12 19:29-0500\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-05 03:29-0400\n" -"Last-Translator: Alexandre Alencar \n" -"Language-Team: Portuguese (Brazil)\n" +"PO-Revision-Date: 2017-06-13 04:05-0400\n" +"Last-Translator: Bruno Guimarães \n" +"Language-Team: Portuguese (Brazil) (https://translate.zanata.org/project/view/GitLab)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +msgid "%{commit_author_link} committed %{commit_timeago}" +msgstr "%{commit_author_link} fez commit %{commit_timeago}" + +msgid "About auto deploy" +msgstr "Sobre a implantação automática" + +msgid "Active" +msgstr "Ativo" + +msgid "Activity" +msgstr "Atividade" + +msgid "Add Changelog" +msgstr "Adicionar registro de mudanças" + +msgid "Add Contribution guide" +msgstr "Adicionar Guia de contribuição" + +msgid "Add License" +msgstr "Adicionar Licença" + +msgid "Add an SSH key to your profile to pull or push via SSH." +msgstr "Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH." + +msgid "Add new directory" +msgstr "Adicionar novo diretório" + +msgid "Archived project! Repository is read-only" +msgstr "Projeto arquivado! O repositório é somente leitura" + +msgid "Are you sure you want to delete this pipeline schedule?" +msgstr "Tem certeza que deseja excluir este agendamento de pipeline?" + +msgid "Attach a file by drag & drop or %{upload_link}" +msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}" + +msgid "Branch" +msgid_plural "Branches" +msgstr[0] "Branch" +msgstr[1] "Branches" + +msgid "" +"Branch %{branch_name} was created. To set up auto deploy, " +"choose a GitLab CI Yaml template and commit your changes. " +"%{link_to_autodeploy_doc}" +msgstr "" +"O branch %{branch_name} foi criado. Para configurar a auto " +"implantação, selecione um modelo de Yaml do GitLab CI e registre suas " +"mudanças. \n" +"%{link_to_autodeploy_doc}" + +msgid "Branches" +msgstr "Branches" + +msgid "Browse files" +msgstr "Navegar pelos arquivos" + msgid "ByAuthor|by" -msgstr "por" +msgstr "ByAuthor|por" + +msgid "CI configuration" +msgstr "Configuração da Integração Contínua" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "ChangeTypeActionLabel|Pick into branch" +msgstr "ChangeTypeActionLabel|Pick para um branch" + +msgid "ChangeTypeActionLabel|Revert in branch" +msgstr "ChangeTypeActionLabel|Reverter no branch" + +msgid "ChangeTypeAction|Cherry-pick" +msgstr "ChangeTypeAction|Cherry-pick" + +msgid "ChangeType|commit" +msgstr "ChangeType|commit" + +msgid "ChangeType|merge request" +msgstr "ChangeType|merge request" + +msgid "Changelog" +msgstr "Registro de mudanças" + +msgid "Charts" +msgstr "Gráficos" + +msgid "Cherry-pick this commit" +msgstr "Cherry-pick esse commit" + +msgid "Cherry-pick this merge-request" +msgstr "Cherry-pick esse merge-request" + +msgid "CiStatusLabel|canceled" +msgstr "CiStatusLabel|cancelado" + +msgid "CiStatusLabel|created" +msgstr "CiStatusLabel|criado" + +msgid "CiStatusLabel|failed" +msgstr "CiStatusLabel|falhou" + +msgid "CiStatusLabel|manual action" +msgstr "CiStatusLabel|ação manual" + +msgid "CiStatusLabel|passed" +msgstr "CiStatusLabel|passou" + +msgid "CiStatusLabel|passed with warnings" +msgstr "CiStatusLabel|passou com avisos" + +msgid "CiStatusLabel|pending" +msgstr "CiStatusLabel|pendente" + +msgid "CiStatusLabel|skipped" +msgstr "CiStatusLabel|ignorado" + +msgid "CiStatusLabel|waiting for manual action" +msgstr "CiStatusLabel|aguardando ação manual" + +msgid "CiStatusText|blocked" +msgstr "CiStatusText|bloqueado" + +msgid "CiStatusText|canceled" +msgstr "CiStatusText|cancelado" + +msgid "CiStatusText|created" +msgstr "CiStatusText|criado" + +msgid "CiStatusText|failed" +msgstr "CiStatusText|falhou" + +msgid "CiStatusText|manual" +msgstr "CiStatusText|manual" + +msgid "CiStatusText|passed" +msgstr "CiStatusText|passou" + +msgid "CiStatusText|pending" +msgstr "CiStatusText|pendente" + +msgid "CiStatusText|skipped" +msgstr "CiStatusText|ignorado" + +msgid "CiStatus|running" +msgstr "CiStatus|executando" msgid "Commit" msgid_plural "Commits" -msgstr[0] "Commit" -msgstr[1] "Commits" +msgstr[0] "Conjunto de mudanças" +msgstr[1] "Conjuntos de mudanças" + +msgid "Commit message" +msgstr "Mensagem do conjunto de mudanças" + +msgid "CommitMessage|Add %{file_name}" +msgstr "CommitMessage|Adicionar %{file_name}" + +msgid "Commits" +msgstr "Conjuntos de mudanças" + +msgid "Commits|History" +msgstr "Commits|Histórico" + +msgid "Committed by" +msgstr "Entregue por" + +msgid "Compare" +msgstr "Comparar" + +msgid "Contribution guide" +msgstr "Guia de contribuição" + +msgid "Contributors" +msgstr "Contribuidores" + +msgid "Copy URL to clipboard" +msgstr "Copiar URL para área de transferência" + +msgid "Copy commit SHA to clipboard" +msgstr "Copiar SHA do conjunto de mudanças para a área de transferência" + +msgid "Create New Directory" +msgstr "Criar Novo Diretório" + +msgid "Create directory" +msgstr "Criar diretório" + +msgid "Create empty bare repository" +msgstr "Criar repositório centralizado vazio" + +msgid "Create merge request" +msgstr "Criar solicitação de incorporação" + +msgid "Create new..." +msgstr "Criar novo..." + +msgid "CreateNewFork|Fork" +msgstr "CreateNewFork|Fork" + +msgid "CreateTag|Tag" +msgstr "CreateTag|Tag" + +msgid "Cron Timezone" +msgstr "Fuso horário do cron" + +msgid "Cron syntax" +msgstr "Sintaxe do cron" + +msgid "Custom" +msgstr "Personalizar" + +msgid "Custom notification events" +msgstr "Eventos de notificação personalizados" + +msgid "" +"Custom notification levels are the same as participating levels. With custom " +"notification levels you will also receive notifications for select events. " +"To find out more, check out %{notification_link}." +msgstr "" +"Níveis de notificação personalizados são equivalentes a níveis de " +"participação. Com níveis de notificação personalizados você também será " +"notificado sobre eventos selecionados. Para mais informações, visite " +"%{notification_link}." + +msgid "Cycle Analytics" +msgstr "Análise de Ciclo" msgid "" "Cycle Analytics gives an overview of how much time it takes to go from idea " @@ -32,63 +252,222 @@ msgstr "" "para ir para produção em seu projeto." msgid "CycleAnalyticsStage|Code" -msgstr "Código" +msgstr "CycleAnalyticsStage|Código" msgid "CycleAnalyticsStage|Issue" -msgstr "Tarefa" +msgstr "CycleAnalyticsStage|Relato" msgid "CycleAnalyticsStage|Plan" -msgstr "Plano" +msgstr "CycleAnalyticsStage|Plano" msgid "CycleAnalyticsStage|Production" -msgstr "Produção" +msgstr "CycleAnalyticsStage|Produção" msgid "CycleAnalyticsStage|Review" -msgstr "Revisão" +msgstr "CycleAnalyticsStage|Revisão" msgid "CycleAnalyticsStage|Staging" -msgstr "Homologação" +msgstr "CycleAnalyticsStage|Homologação" msgid "CycleAnalyticsStage|Test" -msgstr "Teste" +msgstr "CycleAnalyticsStage|Teste" + +msgid "Define a custom pattern with cron syntax" +msgstr "Defina um padrão personalizado utilizando a sintaxe do cron" + +msgid "Delete" +msgstr "Excluir" msgid "Deploy" msgid_plural "Deploys" msgstr[0] "Implantação" msgstr[1] "Implantações" +msgid "Description" +msgstr "Descrição" + +msgid "Directory name" +msgstr "Nome do diretório" + +msgid "Don't show again" +msgstr "Não exibir novamente" + +msgid "Download" +msgstr "Baixar" + +msgid "Download tar" +msgstr "Baixar tar" + +msgid "Download tar.bz2" +msgstr "Baixar tar.bz2" + +msgid "Download tar.gz" +msgstr "Baixar tar.gz" + +msgid "Download zip" +msgstr "Baixar zip" + +msgid "DownloadArtifacts|Download" +msgstr "DownloadArtifacts|Baixar" + +msgid "DownloadCommit|Email Patches" +msgstr "DownloadCommit|Email com as mudanças" + +msgid "DownloadCommit|Plain Diff" +msgstr "DownloadCommit|Arquivo de texto com as mudanças" + +msgid "DownloadSource|Download" +msgstr "DownloadSource|Baixar" + +msgid "Edit" +msgstr "Alterar" + +msgid "Edit Pipeline Schedule %{id}" +msgstr "Alterar Agendamento do Pipeline %{id}" + +msgid "Every day (at 4:00am)" +msgstr "Todos os dias (às 4:00)" + +msgid "Every month (on the 1st at 4:00am)" +msgstr "Todos os meses (no dia primeiro às 4:00)" + +msgid "Every week (Sundays at 4:00am)" +msgstr "Toda semana (domingos às 4:00)" + +msgid "Failed to change the owner" +msgstr "Erro ao alterar o proprietário" + +msgid "Failed to remove the pipeline schedule" +msgstr "Erro ao excluir o agendamento do pipeline" + +msgid "Files" +msgstr "Arquivos" + +msgid "Find by path" +msgstr "Localizar por caminho" + +msgid "Find file" +msgstr "Localizar arquivo" + msgid "FirstPushedBy|First" -msgstr "Primeiro" +msgstr "FirstPushedBy|Primeiro" msgid "FirstPushedBy|pushed by" -msgstr "publicado por" +msgstr "FirstPushedBy|publicado por" + +msgid "Fork" +msgid_plural "Forks" +msgstr[0] "Bifurcação" +msgstr[1] "Bifurcações" + +msgid "ForkedFromProjectPath|Forked from" +msgstr "ForkedFromProjectPath|Forked de" msgid "From issue creation until deploy to production" -msgstr "Da criação de tarefas até a implantação para a produção" +msgstr "Da abertura de tarefas até a implantação para a produção" msgid "From merge request merge until deploy to production" -msgstr "Da incorporação do merge request até a implantação em produção" +msgstr "" +"Da aceitação da solicitação de incorporação até a implantação em produção" + +msgid "Go to your fork" +msgstr "Ir para sua bifurcação" + +msgid "GoToYourFork|Fork" +msgstr "GoToYourFork|Bifurcação" + +msgid "Home" +msgstr "Início" + +msgid "Housekeeping successfully started" +msgstr "Manutenção iniciada com sucesso" + +msgid "Import repository" +msgstr "Importar repositório" + +msgid "Interval Pattern" +msgstr "Padrão de intervalo" msgid "Introducing Cycle Analytics" msgstr "Apresentando a Análise de Ciclo" +msgid "LFSStatus|Disabled" +msgstr "LFSStatus|Desabilitado" + +msgid "LFSStatus|Enabled" +msgstr "LFSStatus|Habilitado" + msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "Último %d dia" msgstr[1] "Últimos %d dias" +msgid "Last Pipeline" +msgstr "Último Pipeline" + +msgid "Last Update" +msgstr "Última Atualização" + +msgid "Last commit" +msgstr "Último conjunto de mudanças" + +msgid "Learn more in the" +msgstr "Saiba mais em" + +msgid "Leave group" +msgstr "Sair do grupo" + +msgid "Leave project" +msgstr "Sair do projeto" + msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" -msgstr[0] "Limitado a mostrar %d evento no máximo" -msgstr[1] "Limitado a mostrar %d eventos no máximo" +msgstr[0] "Limitado a mostrar %d evento, no máximo" +msgstr[1] "Limitado a mostrar %d eventos, no máximo" msgid "Median" msgstr "Mediana" +msgid "MissingSSHKeyWarningLink|add an SSH key" +msgstr "MissingSSHKeyWarningLink|adicione uma chave SSH" + msgid "New Issue" msgid_plural "New Issues" -msgstr[0] "Nova Tarefa" -msgstr[1] "Novas Tarefas" +msgstr[0] "Novo Relato" +msgstr[1] "Novos Relatos" + +msgid "New Pipeline Schedule" +msgstr "Novo Agendamento de Pipeline" + +msgid "New branch" +msgstr "Nova ramificação" + +msgid "New directory" +msgstr "Novo diretório" + +msgid "New file" +msgstr "Novo arquivo" + +msgid "New issue" +msgstr "Novo relato" + +msgid "New merge request" +msgstr "Nova solicitação de incorporação" + +msgid "New schedule" +msgstr "Novo agendamento" + +msgid "New snippet" +msgstr "Novo snippet" + +msgid "New tag" +msgstr "Nova tag" + +msgid "No repository" +msgstr "Nenhum repositório" + +msgid "No schedules" +msgstr "Nenhum agendamento" msgid "Not available" msgstr "Não disponível" @@ -96,114 +475,376 @@ msgstr "Não disponível" msgid "Not enough data" msgstr "Dados insuficientes" +msgid "Notification events" +msgstr "Eventos de notificação" + +msgid "NotificationEvent|Close issue" +msgstr "NotificationEvent|Fechar relato" + +msgid "NotificationEvent|Close merge request" +msgstr "NotificationEvent|Fechar solicitação de incorporação" + +msgid "NotificationEvent|Failed pipeline" +msgstr "NotificationEvent|Falha no pipeline" + +msgid "NotificationEvent|Merge merge request" +msgstr "NotificationEvent|Aceitar merge request" + +msgid "NotificationEvent|New issue" +msgstr "NotificationEvent|Novo relato" + +msgid "NotificationEvent|New merge request" +msgstr "NotificationEvent|Novo merge request" + +msgid "NotificationEvent|New note" +msgstr "NotificationEvent|Novo comentário" + +msgid "NotificationEvent|Reassign issue" +msgstr "NotificationEvent|Reatribuir relato" + +msgid "NotificationEvent|Reassign merge request" +msgstr "NotificationEvent|Reatribuir merge request" + +msgid "NotificationEvent|Reopen issue" +msgstr "NotificationEvent|Reabrir relato" + +msgid "NotificationEvent|Successful pipeline" +msgstr "NotificationEvent|Pipeline bem sucedido" + +msgid "NotificationLevel|Custom" +msgstr "NotificationLevel|Personalizar" + +msgid "NotificationLevel|Disabled" +msgstr "NotificationLevel|Desabilitado" + +msgid "NotificationLevel|Global" +msgstr "NotificationLevel|Global" + +msgid "NotificationLevel|On mention" +msgstr "NotificationLevel|Quando mencionado" + +msgid "NotificationLevel|Participate" +msgstr "NotificationLevel|Participar" + +msgid "NotificationLevel|Watch" +msgstr "NotificationLevel|Observar" + +msgid "OfSearchInADropdown|Filter" +msgstr "OfSearchInADropdown|Filtrar" + msgid "OpenedNDaysAgo|Opened" -msgstr "Aberto" +msgstr "OpenedNDaysAgo|Aberto" + +msgid "Options" +msgstr "Opções" + +msgid "Owner" +msgstr "Proprietário" + +msgid "Pipeline" +msgstr "Pipeline" msgid "Pipeline Health" msgstr "Saúde da Pipeline" +msgid "Pipeline Schedule" +msgstr "Agendamento da Pipeline" + +msgid "Pipeline Schedules" +msgstr "Agendamentos da Pipeline" + +msgid "PipelineSchedules|Activated" +msgstr "PipelineSchedules|Ativado" + +msgid "PipelineSchedules|Active" +msgstr "PipelineSchedules|Ativo" + +msgid "PipelineSchedules|All" +msgstr "PipelineSchedules|Todos" + +msgid "PipelineSchedules|Inactive" +msgstr "PipelineSchedules|Inativo" + +msgid "PipelineSchedules|Next Run" +msgstr "PipelineSchedules|Próxima Execução" + +msgid "PipelineSchedules|None" +msgstr "PipelineSchedules|Nenhum" + +msgid "PipelineSchedules|Provide a short description for this pipeline" +msgstr "PipelineSchedules|Digite uma descrição curta para esta pipeline" + +msgid "PipelineSchedules|Take ownership" +msgstr "PipelineSchedules|Tornar-se proprietário" + +msgid "PipelineSchedules|Target" +msgstr "PipelineSchedules|Destino" + +msgid "Project '%{project_name}' queued for deletion." +msgstr "Projeto'%{project_name}' marcado para exclusão." + +msgid "Project '%{project_name}' was successfully created." +msgstr "Projeto '%{project_name}' criado com sucesso." + +msgid "Project '%{project_name}' was successfully updated." +msgstr "Projeto '%{project_name}' atualizado com sucesso." + +msgid "Project '%{project_name}' will be deleted." +msgstr "Projeto '%{project_name}' será excluído." + +msgid "Project access must be granted explicitly to each user." +msgstr "" +"Acesso ao projeto deve ser concedido explicitamente para cada usuário." + +msgid "Project export could not be deleted." +msgstr "A exportação do projeto não pôde ser excluída." + +msgid "Project export has been deleted." +msgstr "Exportação do projeto excluída." + +msgid "" +"Project export link has expired. Please generate a new export from your " +"project settings." +msgstr "" +"O link para a exportação do projeto expirou. Favor gerar uma nova exportação " +"a partir das configurações do projeto." + +msgid "Project export started. A download link will be sent by email." +msgstr "" +"Exportação do projeto iniciada. Um link para baixá-la será enviado por email." +"" + +msgid "Project home" +msgstr "Página inicial do projeto" + +msgid "ProjectFeature|Disabled" +msgstr "ProjectFeature|Desabilitado" + +msgid "ProjectFeature|Everyone with access" +msgstr "ProjectFeature|Todos que possuem acesso" + +msgid "ProjectFeature|Only team members" +msgstr "ProjectFeature|Apenas membros do time" + +msgid "ProjectFileTree|Name" +msgstr "ProjectFileTree|Nome" + +msgid "ProjectLastActivity|Never" +msgstr "ProjectLastActivity|Nunca" + msgid "ProjectLifecycle|Stage" -msgstr "Etapa" +msgstr "PipelineSchedules|Etapa" + +msgid "ProjectNetworkGraph|Graph" +msgstr "ProjectNetworkGraph|Árvore" msgid "Read more" -msgstr "Ler mais" +msgstr "Leia mais" + +msgid "Readme" +msgstr "Leia-me" + +msgid "RefSwitcher|Branches" +msgstr "RefSwitcher|Ramificações" + +msgid "RefSwitcher|Tags" +msgstr "RefSwitcher|Tags" msgid "Related Commits" -msgstr "Commits Relacionados" +msgstr "Conjuntos de Mudanças Relacionados" msgid "Related Deployed Jobs" -msgstr "Jobs Relacionados Incorporados" +msgstr "Tarefas Implantadas Relacionadas" msgid "Related Issues" -msgstr "Tarefas Relacionadas" +msgstr "Relatos Relacionados" msgid "Related Jobs" -msgstr "Jobs Relacionados" +msgstr "Tarefas Relacionadas" msgid "Related Merge Requests" -msgstr "Merge Requests Relacionados" +msgstr "Solicitações de Incorporação Relacionadas" msgid "Related Merged Requests" -msgstr "Merge Requests Relacionados" +msgstr "Solicitações de Incorporação Aceitas Relacionadas" + +msgid "Remind later" +msgstr "Lembrar mais tarde" + +msgid "Remove project" +msgstr "Remover projeto" + +msgid "Request Access" +msgstr "Solicitar acesso" + +msgid "Revert this commit" +msgstr "Reverter este conjunto de mudanças" + +msgid "Revert this merge-request" +msgstr "Reverter esta solicitação de incorporação" + +msgid "Save pipeline schedule" +msgstr "Salvar agendamento da pipeline" + +msgid "Schedule a new pipeline" +msgstr "Agendar nova pipeline" + +msgid "Scheduling Pipelines" +msgstr "Agendando pipelines" + +msgid "Search branches and tags" +msgstr "Procurar ramificações e tags" + +msgid "Select Archive Format" +msgstr "Selecionar Formato do Arquivo" + +msgid "Select a timezone" +msgstr "Selecionar fuso horário" + +msgid "Select target branch" +msgstr "Selecionar ramificação de destino" + +msgid "Set a password on your account to pull or push via %{protocol}" +msgstr "" +"Defina uma senha para sua conta para aceitar ou entregar código via " +"%{protocol}" + +msgid "Set up CI" +msgstr "Configurar CI" + +msgid "Set up Koding" +msgstr "Configurar Koding" + +msgid "Set up auto deploy" +msgstr "Configurar auto implantação" + +msgid "SetPasswordToCloneLink|set a password" +msgstr "SetPasswordToCloneLink|defina uma senha" msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "Mostrando %d evento" msgstr[1] "Mostrando %d eventos" +msgid "Source code" +msgstr "Código-fonte" + +msgid "StarProject|Star" +msgstr "StarProject|Marcar" + +msgid "Start a new merge request with these changes" +msgstr "" +"Criar uma nova solicitação de incorporação com estas " +"mudanças" + +msgid "Switch branch/tag" +msgstr "Trocar ramificação/tag" + +msgid "Tag" +msgid_plural "Tags" +msgstr[0] "Tag" +msgstr[1] "Tags" + +msgid "Tags" +msgstr "Tags" + +msgid "Target Branch" +msgstr "Ramificação de destino" + msgid "" "The coding stage shows the time from the first commit to creating the merge " "request. The data will automatically be added here once you create your " "first merge request." msgstr "" -"O estágio de codificação mostra o tempo desde o primeiro commit até a " -"criação do merge request. \n" -"Os dados serão automaticamente adicionados aqui uma vez que você tenha " -"criado seu primeiro merge request." +"A etapa de codificação mostra o tempo desde a entrega do primeiro conjunto " +"de mudanças até a criação da solicitação de incorporação. Os dados serão " +"automaticamente adicionados aqui desde o momento de criação da solicitação " +"de incorporação." msgid "The collection of events added to the data gathered for that stage." -msgstr "" -"A coleção de eventos adicionados aos dados coletados para esse estágio." +msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa." + +msgid "The fork relationship has been removed." +msgstr "O relacionamento como fork foi removido." msgid "" "The issue stage shows the time it takes from creating an issue to assigning " "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"O estágio em questão mostra o tempo que leva desde a criação de uma tarefa " -"até a sua assinatura para um milestone, ou a sua adição para a lista no seu " -"Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa." +"A etapa de relatos mostra o tempo que leva desde a criação de um relato até " +"sua atribuição a um marco, ou sua adição a uma lista no seu Quadro de " +"Relatos. Comece a criar relatos para ver dados para esta etapa." msgid "The phase of the development lifecycle." msgstr "A fase do ciclo de vida do desenvolvimento." +msgid "" +"The pipelines schedule runs pipelines in the future, repeatedly, for " +"specific branches or tags. Those scheduled pipelines will inherit limited " +"project access based on their associated user." +msgstr "" +"O agendamento de pipeline executa pipelines no futuro, repetidamente, para " +"ramificações ou tags específicas. Essas pipelines agendadas terão acesso " +"limitado ao projeto baseado no seu usuário associado." + msgid "" "The planning stage shows the time from the previous step to pushing your " "first commit. This time will be added automatically once you push your first " "commit." msgstr "" -"A fase de planejamento mostra o tempo do passo anterior até empurrar o seu " -"primeiro commit. Este tempo será adicionado automaticamente assim que você " -"realizar seu primeiro commit." +"A etapa de planejamento mostra o tempo do passo anterior até a publicação de " +"seu primeiro conjunto de mudanças. Este tempo será adicionado " +"automaticamente assim que você enviar seu primeiro conjunto de mudanças." msgid "" "The production stage shows the total time it takes between creating an issue " "and deploying the code to production. The data will be automatically added " "once you have completed the full idea to production cycle." msgstr "" -"O estágio de produção mostra o tempo total que leva entre criar uma tarefa e " -"implantar o código na produção. Os dados serão adicionados automaticamente " -"até que você complete todo o ciclo de produção." +"A etapa de produção mostra o tempo total que leva entre criar um relato e " +"implantar o código em produção. Os dados serão adicionados automaticamente " +"assim que você completar todo o ciclo de produção." + +msgid "The project can be accessed by any logged in user." +msgstr "O projeto pode ser acessado por qualquer usuário autenticado." + +msgid "The project can be accessed without any authentication." +msgstr "O projeto pode ser acessado sem a necessidade de autenticação." + +msgid "The repository for this project does not exist." +msgstr "O repositório para este projeto não existe." msgid "" "The review stage shows the time from creating the merge request to merging " "it. The data will automatically be added after you merge your first merge " "request." msgstr "" -"A etapa de revisão mostra o tempo de criação de um merge request até que o " -"merge seja feito. Os dados serão automaticamente adicionados depois que você " -"fizer seu primeiro merge request." +"A etapa de revisão mostra o tempo de criação de uma solicitação de " +"incorporação até sua aceitação. Os dados serão automaticamente adicionados " +"depois que sua primeira solicitação de incorporação for aceita." msgid "" "The staging stage shows the time between merging the MR and deploying code " "to the production environment. The data will be automatically added once you " "deploy to production for the first time." msgstr "" -"O estágio de estágio mostra o tempo entre a fusão do MR e o código de " -"implantação para o ambiente de produção. Os dados serão automaticamente " -"adicionados depois de implantar na produção pela primeira vez." +"A etapa de homologação mostra o tempo entre o aceite da solicitação de " +"incorporação e a implantação do código no ambiente de produção. Os dados " +"serão automaticamente adicionados depois que você implantar em produção pela " +"primeira vez." msgid "" "The testing stage shows the time GitLab CI takes to run every pipeline for " "the related merge request. The data will automatically be added after your " "first pipeline finishes running." msgstr "" -"A fase de teste mostra o tempo que o GitLab CI leva para executar cada " -"pipeline para o merge request relacionado. Os dados serão automaticamente " -"adicionados após a conclusão do primeiro pipeline." +"A etapa de testes mostra o tempo que o GitLab CI leva para executar cada " +"pipeline para a solicitação de incorporação associada. Os dados serão " +"automaticamente adicionados após a conclusão do primeiro pipeline." msgid "The time taken by each data entry gathered by that stage." -msgstr "O tempo necessário para cada entrada de dados reunida por essa etapa." +msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa." msgid "" "The value lying at the midpoint of a series of observed values. E.g., " @@ -211,32 +852,164 @@ msgid "" " 6." msgstr "" "O valor situado no ponto médio de uma série de valores observados. Ex., " -"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6." +"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6." + +msgid "" +"This means you can not push code until you create an empty repository or " +"import existing one." +msgstr "" +"Isto significa que você não pode entregar código até que crie um repositório " +"vazio ou importe um existente." msgid "Time before an issue gets scheduled" -msgstr "Tempo até que uma tarefa seja planejada" +msgstr "Tempo até que um relato seja agendado" msgid "Time before an issue starts implementation" -msgstr "Tempo até que uma tarefa comece a ser implementada" +msgstr "Tempo até que um relato comece a ser implementado" msgid "Time between merge request creation and merge/close" -msgstr "Tempo entre a criação do merge request e o merge/fechamento" +msgstr "" +"Tempo entre a criação da solicitação de incorporação e a aceitação/" +"fechamento" msgid "Time until first merge request" -msgstr "Tempo até o primeiro merge request" +msgstr "Tempo até a primeira solicitação de incorporação" + +msgid "Timeago|%s days ago" +msgstr "Timeago|há %s dias" + +msgid "Timeago|%s days remaining" +msgstr "Timeago|%s dias restantes" + +msgid "Timeago|%s hours remaining" +msgstr "Timeago|%s horas restantes" + +msgid "Timeago|%s minutes ago" +msgstr "Timeago|há %s minutos" + +msgid "Timeago|%s minutes remaining" +msgstr "Timeago|%s minutos restantes" + +msgid "Timeago|%s months ago" +msgstr "Timeago|há %s meses" + +msgid "Timeago|%s months remaining" +msgstr "Timeago|%s meses restantes" + +msgid "Timeago|%s seconds remaining" +msgstr "Timeago|%s segundos restantes" + +msgid "Timeago|%s weeks ago" +msgstr "Timeago|há %s semanas" + +msgid "Timeago|%s weeks remaining" +msgstr "Timeago|%s semanas restantes" + +msgid "Timeago|%s years ago" +msgstr "Timeago|há %s anos" + +msgid "Timeago|%s years remaining" +msgstr "Timeago|%s anos restantes" + +msgid "Timeago|1 day remaining" +msgstr "Timeago|1 dia restante" + +msgid "Timeago|1 hour remaining" +msgstr "Timeago|1 hora restante" + +msgid "Timeago|1 minute remaining" +msgstr "Timeago|1 minuto restante" + +msgid "Timeago|1 month remaining" +msgstr "Timeago|1 mês restante" + +msgid "Timeago|1 week remaining" +msgstr "Timeago|1 semana restante" + +msgid "Timeago|1 year remaining" +msgstr "Timeago|1 ano restante" + +msgid "Timeago|Past due" +msgstr "Timeago|Venceu" + +msgid "Timeago|a day ago" +msgstr "Timeago|há um dia" + +msgid "Timeago|a month ago" +msgstr "Timeago|há um mês" + +msgid "Timeago|a week ago" +msgstr "Timeago|há uma semana" + +msgid "Timeago|a while" +msgstr "Timeago|há algum tempo" + +msgid "Timeago|a year ago" +msgstr "Timeago|há um ano" + +msgid "Timeago|about %s hours ago" +msgstr "Timeago|há cerca de %s horas" + +msgid "Timeago|about a minute ago" +msgstr "Timeago|há cerca de um minuto" + +msgid "Timeago|about an hour ago" +msgstr "Timeago|há cerca de uma hora" + +msgid "Timeago|in %s days" +msgstr "Timeago|em %s dias" + +msgid "Timeago|in %s hours" +msgstr "Timeago|em %s horas" + +msgid "Timeago|in %s minutes" +msgstr "Timeago|em %s minutos" + +msgid "Timeago|in %s months" +msgstr "Timeago|em %s meses" + +msgid "Timeago|in %s seconds" +msgstr "Timeago|em %s segundos" + +msgid "Timeago|in %s weeks" +msgstr "Timeago|em %s semanas" + +msgid "Timeago|in %s years" +msgstr "Timeago|em %s anos" + +msgid "Timeago|in 1 day" +msgstr "Timeago|em 1 dia" + +msgid "Timeago|in 1 hour" +msgstr "Timeago|em 1 hora" + +msgid "Timeago|in 1 minute" +msgstr "Timeago|em 1 minuto" + +msgid "Timeago|in 1 month" +msgstr "Timeago|em 1 mês" + +msgid "Timeago|in 1 week" +msgstr "Timeago|em 1 semana" + +msgid "Timeago|in 1 year" +msgstr "Timeago|em 1 ano" + +msgid "Timeago|less than a minute ago" +msgstr "Timeago|há menos de um minuto" msgid "Time|hr" msgid_plural "Time|hrs" -msgstr[0] "h" -msgstr[1] "hs" +msgstr[0] "Time|h" +msgstr[1] "Time|hs" msgid "Time|min" msgid_plural "Time|mins" -msgstr[0] "min" -msgstr[1] "mins" +msgstr[0] "Time|min" +msgstr[1] "Time|mins" msgid "Time|s" -msgstr "s" +msgstr "Time|s" msgid "Total Time" msgstr "Tempo Total" @@ -244,17 +1017,121 @@ msgstr "Tempo Total" msgid "Total test time for all commits/merges" msgstr "Tempo de teste total para todos os commits/merges" +msgid "Unstar" +msgstr "Desmarcar" + +msgid "Upload New File" +msgstr "Enviar Novo Arquivo" + +msgid "Upload file" +msgstr "Enviar arquivo" + +msgid "Use your global notification setting" +msgstr "Utilizar configuração de notificação global" + +msgid "VisibilityLevel|Internal" +msgstr "VisibilityLevel|Interno" + +msgid "VisibilityLevel|Private" +msgstr "VisibilityLevel|Privado" + +msgid "VisibilityLevel|Public" +msgstr "VisibilityLevel|Público" + msgid "Want to see the data? Please ask an administrator for access." msgstr "Precisa visualizar os dados? Solicite acesso ao administrador." msgid "We don't have enough data to show this stage." -msgstr "Não temos dados suficientes para mostrar esta fase." +msgstr "Esta etapa não possui dados suficientes para exibição." + +msgid "Withdraw Access Request" +msgstr "Remover Requisição de Acesso" + +msgid "" +"You are going to remove %{project_name_with_namespace}.\n" +"Removed project CANNOT be restored!\n" +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá remover %{project_name_with_namespace}.\n" +"O projeto removido NÃO PODE ser restaurado!\n" +"Tem certeza ABSOLUTA?" + +msgid "" +"You are going to remove the fork relationship to source project " +"%{forked_from_project}. Are you ABSOLUTELY sure?" +msgstr "" +"Você ira remover o relacionamento de fork com o projeto original " +"%{forked_from_project}. Tem certeza ABSOLUTA?" + +msgid "" +"You are going to transfer %{project_name_with_namespace} to another owner. " +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá transferir %{project_name_with_namespace} para outro proprietário. " +"Tem certeza ABSOLUTA?" + +msgid "You can only add files when you are on a branch" +msgstr "Você somente pode adicionar arquivos quando estiver em um branch" + +msgid "You must sign in to star a project" +msgstr "Você deve estar autenticado para marcar um projeto" msgid "You need permission." msgstr "Você precisa de permissão." +msgid "You will not get any notifications via email" +msgstr "Você não será notificado por email" + +msgid "You will only receive notifications for the events you choose" +msgstr "Você será notificado apenas sobre eventos selecionados" + +msgid "" +"You will only receive notifications for threads you have participated in" +msgstr "Você será notificado apenas sobre tópicos nos quais participou" + +msgid "You will receive notifications for any activity" +msgstr "Você será notificado sobre qualquer atividade" + +msgid "" +"You will receive notifications only for comments in which you were " +"@mentioned" +msgstr "Você será notificado apenas sobre comentários que te @mencionam" + +msgid "" +"You won't be able to pull or push project code via %{protocol} until you " +"%{set_password_link} on your account" +msgstr "" +"Você não poderá fazer pull ou push via %{protocol} até que " +"%{set_password_link} para sua conta" + +msgid "" +"You won't be able to pull or push project code via SSH until you " +"%{add_ssh_key_link} to your profile" +msgstr "" +"Você não conseguirá fazer pull ou push no projeto via SSH até que adicione " +"%{add_ssh_key_link} ao seu perfil" + +msgid "Your name" +msgstr "Seu nome" + msgid "day" msgid_plural "days" msgstr[0] "dia" msgstr[1] "dias" +msgid "notification emails" +msgstr "emails de notificação" + +msgid "parent" +msgid_plural "parents" +msgstr[0] "pai" +msgstr[1] "pais" + +msgid "pipeline schedules documentation" +msgstr "documentação do agendamento de pipelines" + +msgid "with stage" +msgid_plural "with stages" +msgstr[0] "com a etapa" +msgstr[1] "com as etapas" + From 7cbdaef37c0d09c92df6ac45dfaf4fbf879d16c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 13:06:17 +0800 Subject: [PATCH 02/61] add changelog of supplement portuguese brazil translation --- ...33672-supplement_portuguese_brazil_translation_of_i18n.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml new file mode 100644 index 00000000000..605c360115e --- /dev/null +++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml @@ -0,0 +1,4 @@ +--- +title: Supplement Portuguese Brazil translation of Project Page & Repository Page +merge_request: 11958 +author: Huang Tao From 903eeccd74be552001bb2cd21bc2c5f1eb26f94b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 13:08:51 +0800 Subject: [PATCH 03/61] revise changelog --- .../33672-supplement_portuguese_brazil_translation_of_i18n.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml index 605c360115e..d2bdc631d2a 100644 --- a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml +++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml @@ -1,4 +1,4 @@ --- title: Supplement Portuguese Brazil translation of Project Page & Repository Page -merge_request: 11958 +merge_request: 12156 author: Huang Tao From 1c5d783806686fd871f5511243515ec72c68fcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 11:41:45 +0800 Subject: [PATCH 04/61] supplement portuguese brazil translation Fix #33672 --- app/assets/javascripts/locale/pt_BR/app.js | 2 +- ..._portuguese_brazil_translation_of_i18n.yml | 4 + locale/pt_BR/gitlab.po | 1005 +++++++++++++++-- 3 files changed, 947 insertions(+), 64 deletions(-) create mode 100644 changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml diff --git a/app/assets/javascripts/locale/pt_BR/app.js b/app/assets/javascripts/locale/pt_BR/app.js index f2eed3da064..78bcb1f9281 100644 --- a/app/assets/javascripts/locale/pt_BR/app.js +++ b/app/assets/javascripts/locale/pt_BR/app.js @@ -1 +1 @@ -var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-05-04 19:24-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-05 03:29-0400","Last-Translator":"Alexandre Alencar ","Language-Team":"Portuguese (Brazil)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"ByAuthor|by":["por"],"Commit":["Commit","Commits"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["Código"],"CycleAnalyticsStage|Issue":["Tarefa"],"CycleAnalyticsStage|Plan":["Plano"],"CycleAnalyticsStage|Production":["Produção"],"CycleAnalyticsStage|Review":["Revisão"],"CycleAnalyticsStage|Staging":["Homologação"],"CycleAnalyticsStage|Test":["Teste"],"Deploy":["Implantação","Implantações"],"FirstPushedBy|First":["Primeiro"],"FirstPushedBy|pushed by":["publicado por"],"From issue creation until deploy to production":["Da criação de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da incorporação do merge request até a implantação em produção"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"Last %d day":["Último %d dia","Últimos %d dias"],"Limited to showing %d event at most":["Limitado a mostrar %d evento no máximo","Limitado a mostrar %d eventos no máximo"],"Median":["Mediana"],"New Issue":["Nova Tarefa","Novas Tarefas"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"OpenedNDaysAgo|Opened":["Aberto"],"Pipeline Health":["Saúde da Pipeline"],"ProjectLifecycle|Stage":["Etapa"],"Read more":["Ler mais"],"Related Commits":["Commits Relacionados"],"Related Deployed Jobs":["Jobs Relacionados Incorporados"],"Related Issues":["Tarefas Relacionadas"],"Related Jobs":["Jobs Relacionados"],"Related Merge Requests":["Merge Requests Relacionados"],"Related Merged Requests":["Merge Requests Relacionados"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["O estágio de codificação mostra o tempo desde o primeiro commit até a criação do merge request. \\nOs dados serão automaticamente adicionados aqui uma vez que você tenha criado seu primeiro merge request."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para esse estágio."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["O estágio em questão mostra o tempo que leva desde a criação de uma tarefa até a sua assinatura para um milestone, ou a sua adição para a lista no seu Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["A fase de planejamento mostra o tempo do passo anterior até empurrar o seu primeiro commit. Este tempo será adicionado automaticamente assim que você realizar seu primeiro commit."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["O estágio de produção mostra o tempo total que leva entre criar uma tarefa e implantar o código na produção. Os dados serão adicionados automaticamente até que você complete todo o ciclo de produção."],"The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.":["A etapa de revisão mostra o tempo de criação de um merge request até que o merge seja feito. Os dados serão automaticamente adicionados depois que você fizer seu primeiro merge request."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["O estágio de estágio mostra o tempo entre a fusão do MR e o código de implantação para o ambiente de produção. Os dados serão automaticamente adicionados depois de implantar na produção pela primeira vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["A fase de teste mostra o tempo que o GitLab CI leva para executar cada pipeline para o merge request relacionado. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário para cada entrada de dados reunida por essa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6."],"Time before an issue gets scheduled":["Tempo até que uma tarefa seja planejada"],"Time before an issue starts implementation":["Tempo até que uma tarefa comece a ser implementada"],"Time between merge request creation and merge/close":["Tempo entre a criação do merge request e o merge/fechamento"],"Time until first merge request":["Tempo até o primeiro merge request"],"Time|hr":["h","hs"],"Time|min":["min","mins"],"Time|s":["s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Não temos dados suficientes para mostrar esta fase."],"You need permission.":["Você precisa de permissão."],"day":["dia","dias"]}}}; \ No newline at end of file +var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 21:59-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-25 09:38-0400","Last-Translator":"Copied by Zanata ","Language-Team":"Portuguese (Brazil)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} fez commit %{commit_timeago}"],"About auto deploy":["Sobre a implantação automática"],"Active":["Ativo"],"Activity":["Atividade"],"Add Changelog":["Adicionar registro de mudanças"],"Add Contribution guide":["Adicionar Guia de contribuição"],"Add License":["Adicionar Licença"],"Add an SSH key to your profile to pull or push via SSH.":["Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH."],"Add new directory":["Adicionar novo diretório"],"Archived project! Repository is read-only":["Projeto arquivado! O repositório é somente leitura"],"Are you sure you want to delete this pipeline schedule?":["Tem certeza que deseja excluir este agendamento de pipeline?"],"Attach a file by drag & drop or %{upload_link}":["Para anexar arquivo, arraste e solte ou %{upload_link}"],"Branch":["Branch","Branches"],"Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":["O branch %{branch_name} foi criado. Para configurar a implantação automática, selecione um modelo de Yaml do GitLab CI e registre suas mudanças. %{link_to_autodeploy_doc}"],"Branches":["Branches"],"Browse files":["Navegar pelos arquivos"],"ByAuthor|by":["ByAuthor|por"],"CI configuration":["Configuração da Integração Contínua"],"Cancel":["Cancelar"],"ChangeTypeActionLabel|Pick into branch":["ChangeTypeActionLabel|Pick para um branch"],"ChangeTypeActionLabel|Revert in branch":["ChangeTypeActionLabel|Reverter no branch"],"ChangeTypeAction|Cherry-pick":["ChangeTypeAction|Cherry-pick"],"ChangeTypeAction|Revert":["ChangeTypeAction|Reverter"],"Changelog":["Registro de mudanças"],"Charts":["Gráficos"],"Cherry-pick this commit":["Cherry-pick esse commit"],"Cherry-pick this merge request":["Cherry-pick esse merge request"],"CiStatusLabel|canceled":["CiStatusLabel|cancelado"],"CiStatusLabel|created":["CiStatusLabel|criado"],"CiStatusLabel|failed":["CiStatusLabel|falhou"],"CiStatusLabel|manual action":["CiStatusLabel|ação manual"],"CiStatusLabel|passed":["CiStatusLabel|passou"],"CiStatusLabel|passed with warnings":["CiStatusLabel|passou com avisos"],"CiStatusLabel|pending":["CiStatusLabel|pendente"],"CiStatusLabel|skipped":["CiStatusLabel|ignorado"],"CiStatusLabel|waiting for manual action":["CiStatusLabel|aguardando ação manual"],"CiStatusText|blocked":["CiStatusText|bloqueado"],"CiStatusText|canceled":["CiStatusText|cancelado"],"CiStatusText|created":["CiStatusText|criado"],"CiStatusText|failed":["CiStatusText|falhou"],"CiStatusText|manual":["CiStatusText|manual"],"CiStatusText|passed":["CiStatusText|passou"],"CiStatusText|pending":["CiStatusText|pendente"],"CiStatusText|skipped":["CiStatusText|ignorado"],"CiStatus|running":["CiStatus|executando"],"Commit":["Commit","Commits"],"Commit message":["Mensagem de commit"],"CommitBoxTitle|Commit":["CommitBoxTitle|Commit"],"CommitMessage|Add %{file_name}":["CommitMessage|Adicionar %{file_name}"],"Commits":["Commits"],"Commits|History":["Commits|Histórico"],"Committed by":["Commit feito por"],"Compare":["Comparar"],"Contribution guide":["Guia de contribuição"],"Contributors":["Contribuidores"],"Copy URL to clipboard":["Copiar URL para área de transferência"],"Copy commit SHA to clipboard":["Copiar SHA do commit para a área de transferência"],"Create New Directory":["Criar Novo Diretório"],"Create directory":["Criar diretório"],"Create empty bare repository":["Criar repositório bruto vazio"],"Create merge request":["Criar merge request"],"Create new...":["Criar novo..."],"CreateNewFork|Fork":["CreateNewFork|Fork"],"CreateTag|Tag":["CreateTag|Tag"],"Cron Timezone":["Fuso horário do cron"],"Cron syntax":["Sintaxe do cron"],"Custom notification events":["Eventos de notificação personalizados"],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":["Níveis de notificação personalizados são equivalentes a níveis de participação. Com níveis de notificação personalizados você também será notificado sobre eventos selecionados. Para mais informações, visite %{notification_link}."],"Cycle Analytics":["Análise de Ciclo"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["CycleAnalyticsStage|Código"],"CycleAnalyticsStage|Issue":["CycleAnalyticsStage|Issue"],"CycleAnalyticsStage|Plan":["CycleAnalyticsStage|Plano"],"CycleAnalyticsStage|Production":["CycleAnalyticsStage|Produção"],"CycleAnalyticsStage|Review":["CycleAnalyticsStage|Revisão"],"CycleAnalyticsStage|Staging":["CycleAnalyticsStage|Homologação"],"CycleAnalyticsStage|Test":["CycleAnalyticsStage|Teste"],"Define a custom pattern with cron syntax":["Defina um padrão personalizado utilizando a sintaxe do cron"],"Delete":["Excluir"],"Deploy":["Implantação","Implantações"],"Description":["Descrição"],"Directory name":["Nome do diretório"],"Don't show again":["Não exibir novamente"],"Download":["Baixar"],"Download tar":["Baixar tar"],"Download tar.bz2":["Baixar tar.bz2"],"Download tar.gz":["Baixar tar.gz"],"Download zip":["Baixar zip"],"DownloadArtifacts|Download":["DownloadArtifacts|Baixar"],"DownloadCommit|Email Patches":["DownloadCommit|Email com as mudanças"],"DownloadCommit|Plain Diff":["DownloadCommit|Arquivo de texto com as mudanças"],"DownloadSource|Download":["DownloadSource|Baixar"],"Edit":["Alterar"],"Edit Pipeline Schedule %{id}":["Alterar Agendamento do Pipeline %{id}"],"Every day (at 4:00am)":["Todos os dias (às 4:00)"],"Every month (on the 1st at 4:00am)":["Todos os meses (no dia primeiro às 4:00)"],"Every week (Sundays at 4:00am)":["Toda semana (domingos às 4:00)"],"Failed to change the owner":["Erro ao alterar o proprietário"],"Failed to remove the pipeline schedule":["Erro ao excluir o agendamento do pipeline"],"Files":["Arquivos"],"Find by path":["Localizar por caminho"],"Find file":["Localizar arquivo"],"FirstPushedBy|First":["FirstPushedBy|Primeiro"],"FirstPushedBy|pushed by":["FirstPushedBy|publicado por"],"Fork":["Fork","Forks"],"ForkedFromProjectPath|Forked from":["ForkedFromProjectPath|Forked de"],"From issue creation until deploy to production":["Da abertura de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da aceitação da solicitação de incorporação até a implantação em produção"],"Go to your fork":["Ir para seu fork"],"GoToYourFork|Fork":["GoToYourFork|Fork"],"Home":["Início"],"Housekeeping successfully started":["Manutenção iniciada com sucesso"],"Import repository":["Importar repositório"],"Interval Pattern":["Padrão de intervalo"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"LFSStatus|Disabled":["LFSStatus|Desabilitado"],"LFSStatus|Enabled":["LFSStatus|Habilitado"],"Last %d day":["Último %d dia","Últimos %d dias"],"Last Pipeline":["Último Pipeline"],"Last Update":["Última Atualização"],"Last commit":["Último commit"],"Learn more in the":["Saiba mais em"],"Learn more in the|pipeline schedules documentation":["Learn more in the|documentação de agendamento de pipeline"],"Leave group":["Sair do grupo"],"Leave project":["Sair do projeto"],"Limited to showing %d event at most":["Limitado a mostrar %d evento, no máximo","Limitado a mostrar %d eventos, no máximo"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":["MissingSSHKeyWarningLink|adicione uma chave SSH"],"New Issue":["Nova Issue","Novas Issues"],"New Pipeline Schedule":["Novo Agendamento de Pipeline"],"New branch":["Novo branch"],"New directory":["Novo diretório"],"New file":["Novo arquivo"],"New issue":["Nova issue"],"New merge request":["Novo merge request"],"New schedule":["Novo agendamento"],"New snippet":["Novo snippet"],"New tag":["Nova tag"],"No repository":["Nenhum repositório"],"No schedules":["Nenhum agendamento"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"Notification events":["Eventos de notificação"],"NotificationEvent|Close issue":["NotificationEvent|Fechar issue"],"NotificationEvent|Close merge request":["NotificationEvent|Fechar merge request"],"NotificationEvent|Failed pipeline":["NotificationEvent|Falha no pipeline"],"NotificationEvent|Merge merge request":["NotificationEvent|Aceitar merge request"],"NotificationEvent|New issue":["NotificationEvent|Nova issue"],"NotificationEvent|New merge request":["NotificationEvent|Novo merge request"],"NotificationEvent|New note":["NotificationEvent|Novo comentário"],"NotificationEvent|Reassign issue":["NotificationEvent|Reatribuir issue"],"NotificationEvent|Reassign merge request":["NotificationEvent|Reatribuir merge request"],"NotificationEvent|Reopen issue":["NotificationEvent|Reabrir issue"],"NotificationEvent|Successful pipeline":["NotificationEvent|Pipeline bem sucedido"],"NotificationLevel|Custom":["NotificationLevel|Personalizar"],"NotificationLevel|Disabled":["NotificationLevel|Desabilitado"],"NotificationLevel|Global":["NotificationLevel|Global"],"NotificationLevel|On mention":["NotificationLevel|Quando mencionado"],"NotificationLevel|Participate":["NotificationLevel|Participar"],"NotificationLevel|Watch":["NotificationLevel|Observar"],"OfSearchInADropdown|Filter":["OfSearchInADropdown|Filtrar"],"OpenedNDaysAgo|Opened":["OpenedNDaysAgo|Aberto"],"Options":["Opções"],"Owner":["Proprietário"],"Pipeline":["Pipeline"],"Pipeline Health":["Saúde da Pipeline"],"Pipeline Schedule":["Agendamento da Pipeline"],"Pipeline Schedules":["Agendamentos da Pipeline"],"PipelineSchedules|Activated":["PipelineSchedules|Ativado"],"PipelineSchedules|Active":["PipelineSchedules|Ativo"],"PipelineSchedules|All":["PipelineSchedules|Todos"],"PipelineSchedules|Inactive":["PipelineSchedules|Inativo"],"PipelineSchedules|Next Run":["PipelineSchedules|Próxima Execução"],"PipelineSchedules|None":["PipelineSchedules|Nenhum"],"PipelineSchedules|Provide a short description for this pipeline":["PipelineSchedules|Digite uma descrição curta para esta pipeline"],"PipelineSchedules|Take ownership":["PipelineSchedules|Tornar-se proprietário"],"PipelineSchedules|Target":["PipelineSchedules|Destino"],"PipelineSheduleIntervalPattern|Custom":["PipelineSheduleIntervalPattern|Personalizado"],"Pipeline|with stage":["Pipeline|com etapa"],"Pipeline|with stages":["Pipeline|com etapas"],"Project '%{project_name}' queued for deletion.":["Projeto'%{project_name}' marcado para exclusão."],"Project '%{project_name}' was successfully created.":["Projeto '%{project_name}' criado com sucesso."],"Project '%{project_name}' was successfully updated.":["Projeto '%{project_name}' atualizado com sucesso."],"Project '%{project_name}' will be deleted.":["Projeto '%{project_name}' será excluído."],"Project access must be granted explicitly to each user.":["Acesso ao projeto deve ser concedido explicitamente para cada usuário."],"Project export could not be deleted.":["A exportação do projeto não pôde ser excluída."],"Project export has been deleted.":["Exportação do projeto excluída."],"Project export link has expired. Please generate a new export from your project settings.":["O link para a exportação do projeto expirou. Favor gerar uma nova exportação a partir das configurações do projeto."],"Project export started. A download link will be sent by email.":["Exportação do projeto iniciada. Um link para baixá-la será enviado por email."],"Project home":["Página inicial do projeto"],"ProjectFeature|Disabled":["ProjectFeature|Desabilitado"],"ProjectFeature|Everyone with access":["ProjectFeature|Todos que possuem acesso"],"ProjectFeature|Only team members":["ProjectFeature|Apenas membros do time"],"ProjectFileTree|Name":["ProjectFileTree|Nome"],"ProjectLastActivity|Never":["ProjectLastActivity|Nunca"],"ProjectLifecycle|Stage":["PipelineSchedules|Etapa"],"ProjectNetworkGraph|Graph":["ProjectNetworkGraph|Árvore"],"Read more":["Leia mais"],"Readme":["Leia-me"],"RefSwitcher|Branches":["RefSwitcher|Branches"],"RefSwitcher|Tags":["RefSwitcher|Tags"],"Related Commits":["Commits Relacionados"],"Related Deployed Jobs":["Tarefas Implantadas Relacionadas"],"Related Issues":["Issues Relacionadas"],"Related Jobs":["Tarefas Relacionadas"],"Related Merge Requests":["Merge Requests Relacionados"],"Related Merged Requests":["Merge Requests Relacionados"],"Remind later":["Lembrar mais tarde"],"Remove project":["Remover projeto"],"Request Access":["Solicitar acesso"],"Revert this commit":["Reverter este commit"],"Revert this merge request":["Reverter esse merge request"],"Save pipeline schedule":["Salvar agendamento da pipeline"],"Schedule a new pipeline":["Agendar nova pipeline"],"Scheduling Pipelines":["Agendando pipelines"],"Search branches and tags":["Procurar branch e tags"],"Select Archive Format":["Selecionar Formato do Arquivo"],"Select a timezone":["Selecionar fuso horário"],"Select target branch":["Selecionar branch de destino"],"Set a password on your account to pull or push via %{protocol}":["Defina uma senha para sua conta para aceitar ou entregar código via %{protocol}"],"Set up CI":["Configurar CI"],"Set up Koding":["Configurar Koding"],"Set up auto deploy":["Configurar implantação automática"],"SetPasswordToCloneLink|set a password":["SetPasswordToCloneLink|defina uma senha"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":["Código-fonte"],"StarProject|Star":["StarProject|Marcar"],"Start a %{new_merge_request} with these changes":["Iniciar um %{new_merge_request} a partir dessas alterações"],"Switch branch/tag":["Trocar branch/tag"],"Tag":["Tag","Tags"],"Tags":["Tags"],"Target Branch":["Branch de destino"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["A etapa de codificação mostra o tempo desde a entrega do primeiro commit até a criação do merge request. Os dados serão automaticamente adicionados aqui desde o momento de criação do merge request."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para essa etapa."],"The fork relationship has been removed.":["O relacionamento como fork foi removido."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["A etapa de relatos mostra o tempo que leva desde a criação de uma issue até sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. Comece a criar issues para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":["O agendamento de pipeline executa pipelines no futuro, repetidamente, para branches ou tags específicas. Essas pipelines agendadas terão acesso limitado ao projeto baseado no seu usuário associado."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["A etapa de planejamento mostra o tempo do passo anterior até a publicação de seu primeiro conjunto de mudanças. Este tempo será adicionado automaticamente assim que você enviar seu primeiro conjunto de mudanças."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["A etapa de produção mostra o tempo total que leva entre criar uma issue e implantar o código em produção. Os dados serão adicionados automaticamente assim que você completar todo o ciclo de produção."],"The project can be accessed by any logged in user.":["O projeto pode ser acessado por qualquer usuário autenticado."],"The project can be accessed without any authentication.":["O projeto pode ser acessado sem a necessidade de autenticação."],"The repository for this project does not exist.":["Não existe repositório para este projeto."],"The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.":["A etapa de revisão mostra o tempo de criação de uma solicitação de incorporação até sua aceitação. Os dados serão automaticamente adicionados depois que sua primeira solicitação de incorporação for aceita."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["A etapa de homologação mostra o tempo entre o aceite da solicitação de incorporação e a implantação do código no ambiente de produção. Os dados serão automaticamente adicionados depois que você implantar em produção pela primeira vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["A etapa de testes mostra o tempo que o GitLab CI leva para executar cada pipeline para a solicitação de incorporação associada. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário por cada entrada de dados reunida por essa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":["Isto significa que você não pode entregar código até que crie um repositório vazio ou importe um existente."],"Time before an issue gets scheduled":["Tempo até que uma issue seja agendada"],"Time before an issue starts implementation":["Tempo até que uma issue comece a ser implementado"],"Time between merge request creation and merge/close":["Tempo entre a criação da solicitação de incorporação e a aceitação/fechamento"],"Time until first merge request":["Tempo até a primeira solicitação de incorporação"],"Timeago|%s days ago":["Timeago|há %s dias"],"Timeago|%s days remaining":["Timeago|%s dias restantes"],"Timeago|%s hours remaining":["Timeago|%s horas restantes"],"Timeago|%s minutes ago":["Timeago|há %s minutos"],"Timeago|%s minutes remaining":["Timeago|%s minutos restantes"],"Timeago|%s months ago":["Timeago|há %s meses"],"Timeago|%s months remaining":["Timeago|%s meses restantes"],"Timeago|%s seconds remaining":["Timeago|%s segundos restantes"],"Timeago|%s weeks ago":["Timeago|há %s semanas"],"Timeago|%s weeks remaining":["Timeago|%s semanas restantes"],"Timeago|%s years ago":["Timeago|há %s anos"],"Timeago|%s years remaining":["Timeago|%s anos restantes"],"Timeago|1 day remaining":["Timeago|1 dia restante"],"Timeago|1 hour remaining":["Timeago|1 hora restante"],"Timeago|1 minute remaining":["Timeago|1 minuto restante"],"Timeago|1 month remaining":["Timeago|1 mês restante"],"Timeago|1 week remaining":["Timeago|1 semana restante"],"Timeago|1 year remaining":["Timeago|1 ano restante"],"Timeago|Past due":["Timeago|Venceu"],"Timeago|a day ago":["Timeago|há um dia"],"Timeago|a month ago":["Timeago|há um mês"],"Timeago|a week ago":["Timeago|há uma semana"],"Timeago|a while":["Timeago|há algum tempo"],"Timeago|a year ago":["Timeago|há um ano"],"Timeago|about %s hours ago":["Timeago|há cerca de %s horas"],"Timeago|about a minute ago":["Timeago|há cerca de um minuto"],"Timeago|about an hour ago":["Timeago|há cerca de uma hora"],"Timeago|in %s days":["Timeago|em %s dias"],"Timeago|in %s hours":["Timeago|em %s horas"],"Timeago|in %s minutes":["Timeago|em %s minutos"],"Timeago|in %s months":["Timeago|em %s meses"],"Timeago|in %s seconds":["Timeago|em %s segundos"],"Timeago|in %s weeks":["Timeago|em %s semanas"],"Timeago|in %s years":["Timeago|em %s anos"],"Timeago|in 1 day":["Timeago|em 1 dia"],"Timeago|in 1 hour":["Timeago|em 1 hora"],"Timeago|in 1 minute":["Timeago|em 1 minuto"],"Timeago|in 1 month":["Timeago|em 1 mês"],"Timeago|in 1 week":["Timeago|em 1 semana"],"Timeago|in 1 year":["Timeago|em 1 ano"],"Timeago|less than a minute ago":["Timeago|há menos de um minuto"],"Time|hr":["Time|h","Time|hs"],"Time|min":["Time|min","Time|mins"],"Time|s":["Time|s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Unstar":["Desmarcar"],"Upload New File":["Enviar Novo Arquivo"],"Upload file":["Enviar arquivo"],"Use your global notification setting":["Utilizar configuração de notificação global"],"VisibilityLevel|Internal":["VisibilityLevel|Interno"],"VisibilityLevel|Private":["VisibilityLevel|Privado"],"VisibilityLevel|Public":["VisibilityLevel|Público"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Esta etapa não possui dados suficientes para exibição."],"Withdraw Access Request":["Remover Requisição de Acesso"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Você irá remover %{project_name_with_namespace}.\\nO projeto removido NÃO PODE ser restaurado!\\nTem certeza ABSOLUTA?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Você ira remover o relacionamento de fork com o projeto original %{forked_from_project}. Tem certeza ABSOLUTA?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Você irá transferir %{project_name_with_namespace} para outro proprietário. Tem certeza ABSOLUTA?"],"You can only add files when you are on a branch":["Você somente pode adicionar arquivos quando estiver em um branch"],"You have reached your project limit":["Você atingiu o limite de seu projeto"],"You must sign in to star a project":["Você deve estar autenticado para marcar um projeto"],"You need permission.":["Você precisa de permissão."],"You will not get any notifications via email":["Você não será notificado por email"],"You will only receive notifications for the events you choose":["Você será notificado apenas sobre eventos selecionados"],"You will only receive notifications for threads you have participated in":["Você será notificado apenas sobre tópicos nos quais participou"],"You will receive notifications for any activity":["Você será notificado sobre qualquer atividade"],"You will receive notifications only for comments in which you were @mentioned":["Você será notificado apenas sobre comentários que te @mencionam"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["Você não poderá fazer pull ou push via %{protocol} até que %{set_password_link} para sua conta"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["Você não conseguirá fazer pull ou push no projeto via SSH até que adicione %{add_ssh_key_link} ao seu perfil"],"Your name":["Seu nome"],"day":["dia","dias"],"new merge request":["novo merge request"],"notification emails":["emails de notificação"],"parent":["pai","pais"]}}}; \ No newline at end of file diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml new file mode 100644 index 00000000000..d2bdc631d2a --- /dev/null +++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml @@ -0,0 +1,4 @@ +--- +title: Supplement Portuguese Brazil translation of Project Page & Repository Page +merge_request: 12156 +author: Huang Tao diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 5ad41f92b64..6377ed36e48 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,29 +1,244 @@ -# Alexandre Alencar , 2017. #zanata # Fabio Beneditto , 2017. #zanata -# Leandro Nunes dos Santos , 2017. #zanata +# Huang Tao , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-05-04 19:24-0500\n" +"POT-Creation-Date: 2017-06-15 21:59-0500\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-05 03:29-0400\n" -"Last-Translator: Alexandre Alencar \n" +"PO-Revision-Date: 2017-06-25 09:38-0400\n" +"Last-Translator: Copied by Zanata \n" "Language-Team: Portuguese (Brazil)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +msgid "%{commit_author_link} committed %{commit_timeago}" +msgstr "%{commit_author_link} fez commit %{commit_timeago}" + +msgid "About auto deploy" +msgstr "Sobre a implantação automática" + +msgid "Active" +msgstr "Ativo" + +msgid "Activity" +msgstr "Atividade" + +msgid "Add Changelog" +msgstr "Adicionar registro de mudanças" + +msgid "Add Contribution guide" +msgstr "Adicionar Guia de contribuição" + +msgid "Add License" +msgstr "Adicionar Licença" + +msgid "Add an SSH key to your profile to pull or push via SSH." +msgstr "Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH." + +msgid "Add new directory" +msgstr "Adicionar novo diretório" + +msgid "Archived project! Repository is read-only" +msgstr "Projeto arquivado! O repositório é somente leitura" + +msgid "Are you sure you want to delete this pipeline schedule?" +msgstr "Tem certeza que deseja excluir este agendamento de pipeline?" + +msgid "Attach a file by drag & drop or %{upload_link}" +msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}" + +msgid "Branch" +msgid_plural "Branches" +msgstr[0] "Branch" +msgstr[1] "Branches" + +msgid "" +"Branch %{branch_name} was created. To set up auto deploy, " +"choose a GitLab CI Yaml template and commit your changes. " +"%{link_to_autodeploy_doc}" +msgstr "" +"O branch %{branch_name} foi criado. Para configurar a " +"implantação automática, selecione um modelo de Yaml do GitLab CI e registre " +"suas mudanças. %{link_to_autodeploy_doc}" + +msgid "Branches" +msgstr "Branches" + +msgid "Browse files" +msgstr "Navegar pelos arquivos" + msgid "ByAuthor|by" -msgstr "por" +msgstr "ByAuthor|por" + +msgid "CI configuration" +msgstr "Configuração da Integração Contínua" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "ChangeTypeActionLabel|Pick into branch" +msgstr "ChangeTypeActionLabel|Pick para um branch" + +msgid "ChangeTypeActionLabel|Revert in branch" +msgstr "ChangeTypeActionLabel|Reverter no branch" + +msgid "ChangeTypeAction|Cherry-pick" +msgstr "ChangeTypeAction|Cherry-pick" + +msgid "ChangeTypeAction|Revert" +msgstr "ChangeTypeAction|Reverter" + +msgid "Changelog" +msgstr "Registro de mudanças" + +msgid "Charts" +msgstr "Gráficos" + +msgid "Cherry-pick this commit" +msgstr "Cherry-pick esse commit" + +msgid "Cherry-pick this merge request" +msgstr "Cherry-pick esse merge request" + +msgid "CiStatusLabel|canceled" +msgstr "CiStatusLabel|cancelado" + +msgid "CiStatusLabel|created" +msgstr "CiStatusLabel|criado" + +msgid "CiStatusLabel|failed" +msgstr "CiStatusLabel|falhou" + +msgid "CiStatusLabel|manual action" +msgstr "CiStatusLabel|ação manual" + +msgid "CiStatusLabel|passed" +msgstr "CiStatusLabel|passou" + +msgid "CiStatusLabel|passed with warnings" +msgstr "CiStatusLabel|passou com avisos" + +msgid "CiStatusLabel|pending" +msgstr "CiStatusLabel|pendente" + +msgid "CiStatusLabel|skipped" +msgstr "CiStatusLabel|ignorado" + +msgid "CiStatusLabel|waiting for manual action" +msgstr "CiStatusLabel|aguardando ação manual" + +msgid "CiStatusText|blocked" +msgstr "CiStatusText|bloqueado" + +msgid "CiStatusText|canceled" +msgstr "CiStatusText|cancelado" + +msgid "CiStatusText|created" +msgstr "CiStatusText|criado" + +msgid "CiStatusText|failed" +msgstr "CiStatusText|falhou" + +msgid "CiStatusText|manual" +msgstr "CiStatusText|manual" + +msgid "CiStatusText|passed" +msgstr "CiStatusText|passou" + +msgid "CiStatusText|pending" +msgstr "CiStatusText|pendente" + +msgid "CiStatusText|skipped" +msgstr "CiStatusText|ignorado" + +msgid "CiStatus|running" +msgstr "CiStatus|executando" msgid "Commit" msgid_plural "Commits" msgstr[0] "Commit" msgstr[1] "Commits" +msgid "Commit message" +msgstr "Mensagem de commit" + +msgid "CommitBoxTitle|Commit" +msgstr "CommitBoxTitle|Commit" + +msgid "CommitMessage|Add %{file_name}" +msgstr "CommitMessage|Adicionar %{file_name}" + +msgid "Commits" +msgstr "Commits" + +msgid "Commits|History" +msgstr "Commits|Histórico" + +msgid "Committed by" +msgstr "Commit feito por" + +msgid "Compare" +msgstr "Comparar" + +msgid "Contribution guide" +msgstr "Guia de contribuição" + +msgid "Contributors" +msgstr "Contribuidores" + +msgid "Copy URL to clipboard" +msgstr "Copiar URL para área de transferência" + +msgid "Copy commit SHA to clipboard" +msgstr "Copiar SHA do commit para a área de transferência" + +msgid "Create New Directory" +msgstr "Criar Novo Diretório" + +msgid "Create directory" +msgstr "Criar diretório" + +msgid "Create empty bare repository" +msgstr "Criar repositório bruto vazio" + +msgid "Create merge request" +msgstr "Criar merge request" + +msgid "Create new..." +msgstr "Criar novo..." + +msgid "CreateNewFork|Fork" +msgstr "CreateNewFork|Fork" + +msgid "CreateTag|Tag" +msgstr "CreateTag|Tag" + +msgid "Cron Timezone" +msgstr "Fuso horário do cron" + +msgid "Cron syntax" +msgstr "Sintaxe do cron" + +msgid "Custom notification events" +msgstr "Eventos de notificação personalizados" + +msgid "" +"Custom notification levels are the same as participating levels. With custom " +"notification levels you will also receive notifications for select events. " +"To find out more, check out %{notification_link}." +msgstr "" +"Níveis de notificação personalizados são equivalentes a níveis de " +"participação. Com níveis de notificação personalizados você também será " +"notificado sobre eventos selecionados. Para mais informações, visite " +"%{notification_link}." + +msgid "Cycle Analytics" +msgstr "Análise de Ciclo" + msgid "" "Cycle Analytics gives an overview of how much time it takes to go from idea " "to production in your project." @@ -32,63 +247,225 @@ msgstr "" "para ir para produção em seu projeto." msgid "CycleAnalyticsStage|Code" -msgstr "Código" +msgstr "CycleAnalyticsStage|Código" msgid "CycleAnalyticsStage|Issue" -msgstr "Tarefa" +msgstr "CycleAnalyticsStage|Issue" msgid "CycleAnalyticsStage|Plan" -msgstr "Plano" +msgstr "CycleAnalyticsStage|Plano" msgid "CycleAnalyticsStage|Production" -msgstr "Produção" +msgstr "CycleAnalyticsStage|Produção" msgid "CycleAnalyticsStage|Review" -msgstr "Revisão" +msgstr "CycleAnalyticsStage|Revisão" msgid "CycleAnalyticsStage|Staging" -msgstr "Homologação" +msgstr "CycleAnalyticsStage|Homologação" msgid "CycleAnalyticsStage|Test" -msgstr "Teste" +msgstr "CycleAnalyticsStage|Teste" + +msgid "Define a custom pattern with cron syntax" +msgstr "Defina um padrão personalizado utilizando a sintaxe do cron" + +msgid "Delete" +msgstr "Excluir" msgid "Deploy" msgid_plural "Deploys" msgstr[0] "Implantação" msgstr[1] "Implantações" +msgid "Description" +msgstr "Descrição" + +msgid "Directory name" +msgstr "Nome do diretório" + +msgid "Don't show again" +msgstr "Não exibir novamente" + +msgid "Download" +msgstr "Baixar" + +msgid "Download tar" +msgstr "Baixar tar" + +msgid "Download tar.bz2" +msgstr "Baixar tar.bz2" + +msgid "Download tar.gz" +msgstr "Baixar tar.gz" + +msgid "Download zip" +msgstr "Baixar zip" + +msgid "DownloadArtifacts|Download" +msgstr "DownloadArtifacts|Baixar" + +msgid "DownloadCommit|Email Patches" +msgstr "DownloadCommit|Email com as mudanças" + +msgid "DownloadCommit|Plain Diff" +msgstr "DownloadCommit|Arquivo de texto com as mudanças" + +msgid "DownloadSource|Download" +msgstr "DownloadSource|Baixar" + +msgid "Edit" +msgstr "Alterar" + +msgid "Edit Pipeline Schedule %{id}" +msgstr "Alterar Agendamento do Pipeline %{id}" + +msgid "Every day (at 4:00am)" +msgstr "Todos os dias (às 4:00)" + +msgid "Every month (on the 1st at 4:00am)" +msgstr "Todos os meses (no dia primeiro às 4:00)" + +msgid "Every week (Sundays at 4:00am)" +msgstr "Toda semana (domingos às 4:00)" + +msgid "Failed to change the owner" +msgstr "Erro ao alterar o proprietário" + +msgid "Failed to remove the pipeline schedule" +msgstr "Erro ao excluir o agendamento do pipeline" + +msgid "Files" +msgstr "Arquivos" + +msgid "Find by path" +msgstr "Localizar por caminho" + +msgid "Find file" +msgstr "Localizar arquivo" + msgid "FirstPushedBy|First" -msgstr "Primeiro" +msgstr "FirstPushedBy|Primeiro" msgid "FirstPushedBy|pushed by" -msgstr "publicado por" +msgstr "FirstPushedBy|publicado por" + +msgid "Fork" +msgid_plural "Forks" +msgstr[0] "Fork" +msgstr[1] "Forks" + +msgid "ForkedFromProjectPath|Forked from" +msgstr "ForkedFromProjectPath|Forked de" msgid "From issue creation until deploy to production" -msgstr "Da criação de tarefas até a implantação para a produção" +msgstr "Da abertura de tarefas até a implantação para a produção" msgid "From merge request merge until deploy to production" -msgstr "Da incorporação do merge request até a implantação em produção" +msgstr "" +"Da aceitação da solicitação de incorporação até a implantação em produção" + +msgid "Go to your fork" +msgstr "Ir para seu fork" + +msgid "GoToYourFork|Fork" +msgstr "GoToYourFork|Fork" + +msgid "Home" +msgstr "Início" + +msgid "Housekeeping successfully started" +msgstr "Manutenção iniciada com sucesso" + +msgid "Import repository" +msgstr "Importar repositório" + +msgid "Interval Pattern" +msgstr "Padrão de intervalo" msgid "Introducing Cycle Analytics" msgstr "Apresentando a Análise de Ciclo" +msgid "LFSStatus|Disabled" +msgstr "LFSStatus|Desabilitado" + +msgid "LFSStatus|Enabled" +msgstr "LFSStatus|Habilitado" + msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "Último %d dia" msgstr[1] "Últimos %d dias" +msgid "Last Pipeline" +msgstr "Último Pipeline" + +msgid "Last Update" +msgstr "Última Atualização" + +msgid "Last commit" +msgstr "Último commit" + +msgid "Learn more in the" +msgstr "Saiba mais em" + +msgid "Learn more in the|pipeline schedules documentation" +msgstr "Learn more in the|documentação de agendamento de pipeline" + +msgid "Leave group" +msgstr "Sair do grupo" + +msgid "Leave project" +msgstr "Sair do projeto" + msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" -msgstr[0] "Limitado a mostrar %d evento no máximo" -msgstr[1] "Limitado a mostrar %d eventos no máximo" +msgstr[0] "Limitado a mostrar %d evento, no máximo" +msgstr[1] "Limitado a mostrar %d eventos, no máximo" msgid "Median" msgstr "Mediana" +msgid "MissingSSHKeyWarningLink|add an SSH key" +msgstr "MissingSSHKeyWarningLink|adicione uma chave SSH" + msgid "New Issue" msgid_plural "New Issues" -msgstr[0] "Nova Tarefa" -msgstr[1] "Novas Tarefas" +msgstr[0] "Nova Issue" +msgstr[1] "Novas Issues" + +msgid "New Pipeline Schedule" +msgstr "Novo Agendamento de Pipeline" + +msgid "New branch" +msgstr "Novo branch" + +msgid "New directory" +msgstr "Novo diretório" + +msgid "New file" +msgstr "Novo arquivo" + +msgid "New issue" +msgstr "Nova issue" + +msgid "New merge request" +msgstr "Novo merge request" + +msgid "New schedule" +msgstr "Novo agendamento" + +msgid "New snippet" +msgstr "Novo snippet" + +msgid "New tag" +msgstr "Nova tag" + +msgid "No repository" +msgstr "Nenhum repositório" + +msgid "No schedules" +msgstr "Nenhum agendamento" msgid "Not available" msgstr "Não disponível" @@ -96,29 +473,201 @@ msgstr "Não disponível" msgid "Not enough data" msgstr "Dados insuficientes" +msgid "Notification events" +msgstr "Eventos de notificação" + +msgid "NotificationEvent|Close issue" +msgstr "NotificationEvent|Fechar issue" + +msgid "NotificationEvent|Close merge request" +msgstr "NotificationEvent|Fechar merge request" + +msgid "NotificationEvent|Failed pipeline" +msgstr "NotificationEvent|Falha no pipeline" + +msgid "NotificationEvent|Merge merge request" +msgstr "NotificationEvent|Aceitar merge request" + +msgid "NotificationEvent|New issue" +msgstr "NotificationEvent|Nova issue" + +msgid "NotificationEvent|New merge request" +msgstr "NotificationEvent|Novo merge request" + +msgid "NotificationEvent|New note" +msgstr "NotificationEvent|Novo comentário" + +msgid "NotificationEvent|Reassign issue" +msgstr "NotificationEvent|Reatribuir issue" + +msgid "NotificationEvent|Reassign merge request" +msgstr "NotificationEvent|Reatribuir merge request" + +msgid "NotificationEvent|Reopen issue" +msgstr "NotificationEvent|Reabrir issue" + +msgid "NotificationEvent|Successful pipeline" +msgstr "NotificationEvent|Pipeline bem sucedido" + +msgid "NotificationLevel|Custom" +msgstr "NotificationLevel|Personalizar" + +msgid "NotificationLevel|Disabled" +msgstr "NotificationLevel|Desabilitado" + +msgid "NotificationLevel|Global" +msgstr "NotificationLevel|Global" + +msgid "NotificationLevel|On mention" +msgstr "NotificationLevel|Quando mencionado" + +msgid "NotificationLevel|Participate" +msgstr "NotificationLevel|Participar" + +msgid "NotificationLevel|Watch" +msgstr "NotificationLevel|Observar" + +msgid "OfSearchInADropdown|Filter" +msgstr "OfSearchInADropdown|Filtrar" + msgid "OpenedNDaysAgo|Opened" -msgstr "Aberto" +msgstr "OpenedNDaysAgo|Aberto" + +msgid "Options" +msgstr "Opções" + +msgid "Owner" +msgstr "Proprietário" + +msgid "Pipeline" +msgstr "Pipeline" msgid "Pipeline Health" msgstr "Saúde da Pipeline" +msgid "Pipeline Schedule" +msgstr "Agendamento da Pipeline" + +msgid "Pipeline Schedules" +msgstr "Agendamentos da Pipeline" + +msgid "PipelineSchedules|Activated" +msgstr "PipelineSchedules|Ativado" + +msgid "PipelineSchedules|Active" +msgstr "PipelineSchedules|Ativo" + +msgid "PipelineSchedules|All" +msgstr "PipelineSchedules|Todos" + +msgid "PipelineSchedules|Inactive" +msgstr "PipelineSchedules|Inativo" + +msgid "PipelineSchedules|Next Run" +msgstr "PipelineSchedules|Próxima Execução" + +msgid "PipelineSchedules|None" +msgstr "PipelineSchedules|Nenhum" + +msgid "PipelineSchedules|Provide a short description for this pipeline" +msgstr "PipelineSchedules|Digite uma descrição curta para esta pipeline" + +msgid "PipelineSchedules|Take ownership" +msgstr "PipelineSchedules|Tornar-se proprietário" + +msgid "PipelineSchedules|Target" +msgstr "PipelineSchedules|Destino" + +msgid "PipelineSheduleIntervalPattern|Custom" +msgstr "PipelineSheduleIntervalPattern|Personalizado" + +msgid "Pipeline|with stage" +msgstr "Pipeline|com etapa" + +msgid "Pipeline|with stages" +msgstr "Pipeline|com etapas" + +msgid "Project '%{project_name}' queued for deletion." +msgstr "Projeto'%{project_name}' marcado para exclusão." + +msgid "Project '%{project_name}' was successfully created." +msgstr "Projeto '%{project_name}' criado com sucesso." + +msgid "Project '%{project_name}' was successfully updated." +msgstr "Projeto '%{project_name}' atualizado com sucesso." + +msgid "Project '%{project_name}' will be deleted." +msgstr "Projeto '%{project_name}' será excluído." + +msgid "Project access must be granted explicitly to each user." +msgstr "" +"Acesso ao projeto deve ser concedido explicitamente para cada usuário." + +msgid "Project export could not be deleted." +msgstr "A exportação do projeto não pôde ser excluída." + +msgid "Project export has been deleted." +msgstr "Exportação do projeto excluída." + +msgid "" +"Project export link has expired. Please generate a new export from your " +"project settings." +msgstr "" +"O link para a exportação do projeto expirou. Favor gerar uma nova exportação " +"a partir das configurações do projeto." + +msgid "Project export started. A download link will be sent by email." +msgstr "" +"Exportação do projeto iniciada. Um link para baixá-la será enviado por email." +"" + +msgid "Project home" +msgstr "Página inicial do projeto" + +msgid "ProjectFeature|Disabled" +msgstr "ProjectFeature|Desabilitado" + +msgid "ProjectFeature|Everyone with access" +msgstr "ProjectFeature|Todos que possuem acesso" + +msgid "ProjectFeature|Only team members" +msgstr "ProjectFeature|Apenas membros do time" + +msgid "ProjectFileTree|Name" +msgstr "ProjectFileTree|Nome" + +msgid "ProjectLastActivity|Never" +msgstr "ProjectLastActivity|Nunca" + msgid "ProjectLifecycle|Stage" -msgstr "Etapa" +msgstr "PipelineSchedules|Etapa" + +msgid "ProjectNetworkGraph|Graph" +msgstr "ProjectNetworkGraph|Árvore" msgid "Read more" -msgstr "Ler mais" +msgstr "Leia mais" + +msgid "Readme" +msgstr "Leia-me" + +msgid "RefSwitcher|Branches" +msgstr "RefSwitcher|Branches" + +msgid "RefSwitcher|Tags" +msgstr "RefSwitcher|Tags" msgid "Related Commits" msgstr "Commits Relacionados" msgid "Related Deployed Jobs" -msgstr "Jobs Relacionados Incorporados" +msgstr "Tarefas Implantadas Relacionadas" msgid "Related Issues" -msgstr "Tarefas Relacionadas" +msgstr "Issues Relacionadas" msgid "Related Jobs" -msgstr "Jobs Relacionados" +msgstr "Tarefas Relacionadas" msgid "Related Merge Requests" msgstr "Merge Requests Relacionados" @@ -126,84 +675,180 @@ msgstr "Merge Requests Relacionados" msgid "Related Merged Requests" msgstr "Merge Requests Relacionados" +msgid "Remind later" +msgstr "Lembrar mais tarde" + +msgid "Remove project" +msgstr "Remover projeto" + +msgid "Request Access" +msgstr "Solicitar acesso" + +msgid "Revert this commit" +msgstr "Reverter este commit" + +msgid "Revert this merge request" +msgstr "Reverter esse merge request" + +msgid "Save pipeline schedule" +msgstr "Salvar agendamento da pipeline" + +msgid "Schedule a new pipeline" +msgstr "Agendar nova pipeline" + +msgid "Scheduling Pipelines" +msgstr "Agendando pipelines" + +msgid "Search branches and tags" +msgstr "Procurar branch e tags" + +msgid "Select Archive Format" +msgstr "Selecionar Formato do Arquivo" + +msgid "Select a timezone" +msgstr "Selecionar fuso horário" + +msgid "Select target branch" +msgstr "Selecionar branch de destino" + +msgid "Set a password on your account to pull or push via %{protocol}" +msgstr "" +"Defina uma senha para sua conta para aceitar ou entregar código via " +"%{protocol}" + +msgid "Set up CI" +msgstr "Configurar CI" + +msgid "Set up Koding" +msgstr "Configurar Koding" + +msgid "Set up auto deploy" +msgstr "Configurar implantação automática" + +msgid "SetPasswordToCloneLink|set a password" +msgstr "SetPasswordToCloneLink|defina uma senha" + msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "Mostrando %d evento" msgstr[1] "Mostrando %d eventos" +msgid "Source code" +msgstr "Código-fonte" + +msgid "StarProject|Star" +msgstr "StarProject|Marcar" + +msgid "Start a %{new_merge_request} with these changes" +msgstr "Iniciar um %{new_merge_request} a partir dessas alterações" + +msgid "Switch branch/tag" +msgstr "Trocar branch/tag" + +msgid "Tag" +msgid_plural "Tags" +msgstr[0] "Tag" +msgstr[1] "Tags" + +msgid "Tags" +msgstr "Tags" + +msgid "Target Branch" +msgstr "Branch de destino" + msgid "" "The coding stage shows the time from the first commit to creating the merge " "request. The data will automatically be added here once you create your " "first merge request." msgstr "" -"O estágio de codificação mostra o tempo desde o primeiro commit até a " -"criação do merge request. \n" -"Os dados serão automaticamente adicionados aqui uma vez que você tenha " -"criado seu primeiro merge request." +"A etapa de codificação mostra o tempo desde a entrega do primeiro commit até " +"a criação do merge request. Os dados serão automaticamente adicionados aqui " +"desde o momento de criação do merge request." msgid "The collection of events added to the data gathered for that stage." -msgstr "" -"A coleção de eventos adicionados aos dados coletados para esse estágio." +msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa." + +msgid "The fork relationship has been removed." +msgstr "O relacionamento como fork foi removido." msgid "" "The issue stage shows the time it takes from creating an issue to assigning " "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"O estágio em questão mostra o tempo que leva desde a criação de uma tarefa " -"até a sua assinatura para um milestone, ou a sua adição para a lista no seu " -"Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa." +"A etapa de relatos mostra o tempo que leva desde a criação de uma issue até " +"sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. " +"Comece a criar issues para ver dados para esta etapa." msgid "The phase of the development lifecycle." msgstr "A fase do ciclo de vida do desenvolvimento." +msgid "" +"The pipelines schedule runs pipelines in the future, repeatedly, for " +"specific branches or tags. Those scheduled pipelines will inherit limited " +"project access based on their associated user." +msgstr "" +"O agendamento de pipeline executa pipelines no futuro, repetidamente, para " +"branches ou tags específicas. Essas pipelines agendadas terão acesso " +"limitado ao projeto baseado no seu usuário associado." + msgid "" "The planning stage shows the time from the previous step to pushing your " "first commit. This time will be added automatically once you push your first " "commit." msgstr "" -"A fase de planejamento mostra o tempo do passo anterior até empurrar o seu " -"primeiro commit. Este tempo será adicionado automaticamente assim que você " -"realizar seu primeiro commit." +"A etapa de planejamento mostra o tempo do passo anterior até a publicação de " +"seu primeiro conjunto de mudanças. Este tempo será adicionado " +"automaticamente assim que você enviar seu primeiro conjunto de mudanças." msgid "" "The production stage shows the total time it takes between creating an issue " "and deploying the code to production. The data will be automatically added " "once you have completed the full idea to production cycle." msgstr "" -"O estágio de produção mostra o tempo total que leva entre criar uma tarefa e " -"implantar o código na produção. Os dados serão adicionados automaticamente " -"até que você complete todo o ciclo de produção." +"A etapa de produção mostra o tempo total que leva entre criar uma issue e " +"implantar o código em produção. Os dados serão adicionados automaticamente " +"assim que você completar todo o ciclo de produção." + +msgid "The project can be accessed by any logged in user." +msgstr "O projeto pode ser acessado por qualquer usuário autenticado." + +msgid "The project can be accessed without any authentication." +msgstr "O projeto pode ser acessado sem a necessidade de autenticação." + +msgid "The repository for this project does not exist." +msgstr "Não existe repositório para este projeto." msgid "" "The review stage shows the time from creating the merge request to merging " "it. The data will automatically be added after you merge your first merge " "request." msgstr "" -"A etapa de revisão mostra o tempo de criação de um merge request até que o " -"merge seja feito. Os dados serão automaticamente adicionados depois que você " -"fizer seu primeiro merge request." +"A etapa de revisão mostra o tempo de criação de uma solicitação de " +"incorporação até sua aceitação. Os dados serão automaticamente adicionados " +"depois que sua primeira solicitação de incorporação for aceita." msgid "" "The staging stage shows the time between merging the MR and deploying code " "to the production environment. The data will be automatically added once you " "deploy to production for the first time." msgstr "" -"O estágio de estágio mostra o tempo entre a fusão do MR e o código de " -"implantação para o ambiente de produção. Os dados serão automaticamente " -"adicionados depois de implantar na produção pela primeira vez." +"A etapa de homologação mostra o tempo entre o aceite da solicitação de " +"incorporação e a implantação do código no ambiente de produção. Os dados " +"serão automaticamente adicionados depois que você implantar em produção pela " +"primeira vez." msgid "" "The testing stage shows the time GitLab CI takes to run every pipeline for " "the related merge request. The data will automatically be added after your " "first pipeline finishes running." msgstr "" -"A fase de teste mostra o tempo que o GitLab CI leva para executar cada " -"pipeline para o merge request relacionado. Os dados serão automaticamente " -"adicionados após a conclusão do primeiro pipeline." +"A etapa de testes mostra o tempo que o GitLab CI leva para executar cada " +"pipeline para a solicitação de incorporação associada. Os dados serão " +"automaticamente adicionados após a conclusão do primeiro pipeline." msgid "The time taken by each data entry gathered by that stage." -msgstr "O tempo necessário para cada entrada de dados reunida por essa etapa." +msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa." msgid "" "The value lying at the midpoint of a series of observed values. E.g., " @@ -211,32 +856,164 @@ msgid "" " 6." msgstr "" "O valor situado no ponto médio de uma série de valores observados. Ex., " -"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6." +"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6." + +msgid "" +"This means you can not push code until you create an empty repository or " +"import existing one." +msgstr "" +"Isto significa que você não pode entregar código até que crie um repositório " +"vazio ou importe um existente." msgid "Time before an issue gets scheduled" -msgstr "Tempo até que uma tarefa seja planejada" +msgstr "Tempo até que uma issue seja agendada" msgid "Time before an issue starts implementation" -msgstr "Tempo até que uma tarefa comece a ser implementada" +msgstr "Tempo até que uma issue comece a ser implementado" msgid "Time between merge request creation and merge/close" -msgstr "Tempo entre a criação do merge request e o merge/fechamento" +msgstr "" +"Tempo entre a criação da solicitação de incorporação e a aceitação/" +"fechamento" msgid "Time until first merge request" -msgstr "Tempo até o primeiro merge request" +msgstr "Tempo até a primeira solicitação de incorporação" + +msgid "Timeago|%s days ago" +msgstr "Timeago|há %s dias" + +msgid "Timeago|%s days remaining" +msgstr "Timeago|%s dias restantes" + +msgid "Timeago|%s hours remaining" +msgstr "Timeago|%s horas restantes" + +msgid "Timeago|%s minutes ago" +msgstr "Timeago|há %s minutos" + +msgid "Timeago|%s minutes remaining" +msgstr "Timeago|%s minutos restantes" + +msgid "Timeago|%s months ago" +msgstr "Timeago|há %s meses" + +msgid "Timeago|%s months remaining" +msgstr "Timeago|%s meses restantes" + +msgid "Timeago|%s seconds remaining" +msgstr "Timeago|%s segundos restantes" + +msgid "Timeago|%s weeks ago" +msgstr "Timeago|há %s semanas" + +msgid "Timeago|%s weeks remaining" +msgstr "Timeago|%s semanas restantes" + +msgid "Timeago|%s years ago" +msgstr "Timeago|há %s anos" + +msgid "Timeago|%s years remaining" +msgstr "Timeago|%s anos restantes" + +msgid "Timeago|1 day remaining" +msgstr "Timeago|1 dia restante" + +msgid "Timeago|1 hour remaining" +msgstr "Timeago|1 hora restante" + +msgid "Timeago|1 minute remaining" +msgstr "Timeago|1 minuto restante" + +msgid "Timeago|1 month remaining" +msgstr "Timeago|1 mês restante" + +msgid "Timeago|1 week remaining" +msgstr "Timeago|1 semana restante" + +msgid "Timeago|1 year remaining" +msgstr "Timeago|1 ano restante" + +msgid "Timeago|Past due" +msgstr "Timeago|Venceu" + +msgid "Timeago|a day ago" +msgstr "Timeago|há um dia" + +msgid "Timeago|a month ago" +msgstr "Timeago|há um mês" + +msgid "Timeago|a week ago" +msgstr "Timeago|há uma semana" + +msgid "Timeago|a while" +msgstr "Timeago|há algum tempo" + +msgid "Timeago|a year ago" +msgstr "Timeago|há um ano" + +msgid "Timeago|about %s hours ago" +msgstr "Timeago|há cerca de %s horas" + +msgid "Timeago|about a minute ago" +msgstr "Timeago|há cerca de um minuto" + +msgid "Timeago|about an hour ago" +msgstr "Timeago|há cerca de uma hora" + +msgid "Timeago|in %s days" +msgstr "Timeago|em %s dias" + +msgid "Timeago|in %s hours" +msgstr "Timeago|em %s horas" + +msgid "Timeago|in %s minutes" +msgstr "Timeago|em %s minutos" + +msgid "Timeago|in %s months" +msgstr "Timeago|em %s meses" + +msgid "Timeago|in %s seconds" +msgstr "Timeago|em %s segundos" + +msgid "Timeago|in %s weeks" +msgstr "Timeago|em %s semanas" + +msgid "Timeago|in %s years" +msgstr "Timeago|em %s anos" + +msgid "Timeago|in 1 day" +msgstr "Timeago|em 1 dia" + +msgid "Timeago|in 1 hour" +msgstr "Timeago|em 1 hora" + +msgid "Timeago|in 1 minute" +msgstr "Timeago|em 1 minuto" + +msgid "Timeago|in 1 month" +msgstr "Timeago|em 1 mês" + +msgid "Timeago|in 1 week" +msgstr "Timeago|em 1 semana" + +msgid "Timeago|in 1 year" +msgstr "Timeago|em 1 ano" + +msgid "Timeago|less than a minute ago" +msgstr "Timeago|há menos de um minuto" msgid "Time|hr" msgid_plural "Time|hrs" -msgstr[0] "h" -msgstr[1] "hs" +msgstr[0] "Time|h" +msgstr[1] "Time|hs" msgid "Time|min" msgid_plural "Time|mins" -msgstr[0] "min" -msgstr[1] "mins" +msgstr[0] "Time|min" +msgstr[1] "Time|mins" msgid "Time|s" -msgstr "s" +msgstr "Time|s" msgid "Total Time" msgstr "Tempo Total" @@ -244,17 +1021,119 @@ msgstr "Tempo Total" msgid "Total test time for all commits/merges" msgstr "Tempo de teste total para todos os commits/merges" +msgid "Unstar" +msgstr "Desmarcar" + +msgid "Upload New File" +msgstr "Enviar Novo Arquivo" + +msgid "Upload file" +msgstr "Enviar arquivo" + +msgid "Use your global notification setting" +msgstr "Utilizar configuração de notificação global" + +msgid "VisibilityLevel|Internal" +msgstr "VisibilityLevel|Interno" + +msgid "VisibilityLevel|Private" +msgstr "VisibilityLevel|Privado" + +msgid "VisibilityLevel|Public" +msgstr "VisibilityLevel|Público" + msgid "Want to see the data? Please ask an administrator for access." msgstr "Precisa visualizar os dados? Solicite acesso ao administrador." msgid "We don't have enough data to show this stage." -msgstr "Não temos dados suficientes para mostrar esta fase." +msgstr "Esta etapa não possui dados suficientes para exibição." + +msgid "Withdraw Access Request" +msgstr "Remover Requisição de Acesso" + +msgid "" +"You are going to remove %{project_name_with_namespace}.\n" +"Removed project CANNOT be restored!\n" +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá remover %{project_name_with_namespace}.\n" +"O projeto removido NÃO PODE ser restaurado!\n" +"Tem certeza ABSOLUTA?" + +msgid "" +"You are going to remove the fork relationship to source project " +"%{forked_from_project}. Are you ABSOLUTELY sure?" +msgstr "" +"Você ira remover o relacionamento de fork com o projeto original " +"%{forked_from_project}. Tem certeza ABSOLUTA?" + +msgid "" +"You are going to transfer %{project_name_with_namespace} to another owner. " +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá transferir %{project_name_with_namespace} para outro proprietário. " +"Tem certeza ABSOLUTA?" + +msgid "You can only add files when you are on a branch" +msgstr "Você somente pode adicionar arquivos quando estiver em um branch" + +msgid "You have reached your project limit" +msgstr "Você atingiu o limite de seu projeto" + +msgid "You must sign in to star a project" +msgstr "Você deve estar autenticado para marcar um projeto" msgid "You need permission." msgstr "Você precisa de permissão." +msgid "You will not get any notifications via email" +msgstr "Você não será notificado por email" + +msgid "You will only receive notifications for the events you choose" +msgstr "Você será notificado apenas sobre eventos selecionados" + +msgid "" +"You will only receive notifications for threads you have participated in" +msgstr "Você será notificado apenas sobre tópicos nos quais participou" + +msgid "You will receive notifications for any activity" +msgstr "Você será notificado sobre qualquer atividade" + +msgid "" +"You will receive notifications only for comments in which you were " +"@mentioned" +msgstr "Você será notificado apenas sobre comentários que te @mencionam" + +msgid "" +"You won't be able to pull or push project code via %{protocol} until you " +"%{set_password_link} on your account" +msgstr "" +"Você não poderá fazer pull ou push via %{protocol} até que " +"%{set_password_link} para sua conta" + +msgid "" +"You won't be able to pull or push project code via SSH until you " +"%{add_ssh_key_link} to your profile" +msgstr "" +"Você não conseguirá fazer pull ou push no projeto via SSH até que adicione " +"%{add_ssh_key_link} ao seu perfil" + +msgid "Your name" +msgstr "Seu nome" + msgid "day" msgid_plural "days" msgstr[0] "dia" msgstr[1] "dias" +msgid "new merge request" +msgstr "novo merge request" + +msgid "notification emails" +msgstr "emails de notificação" + +msgid "parent" +msgid_plural "parents" +msgstr[0] "pai" +msgstr[1] "pais" + From d117d5ac6f80f66baaa9842e54e08df4ca32e7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 28 Jun 2017 18:31:42 +0800 Subject: [PATCH 05/61] Delete JSON files generated from PO files --- app/assets/javascripts/locale/pt_BR/app.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 app/assets/javascripts/locale/pt_BR/app.js diff --git a/app/assets/javascripts/locale/pt_BR/app.js b/app/assets/javascripts/locale/pt_BR/app.js deleted file mode 100644 index 78bcb1f9281..00000000000 --- a/app/assets/javascripts/locale/pt_BR/app.js +++ /dev/null @@ -1 +0,0 @@ -var locales = locales || {}; locales['pt_BR'] = {"domain":"app","locale_data":{"app":{"":{"Project-Id-Version":"gitlab 1.0.0","Report-Msgid-Bugs-To":"","POT-Creation-Date":"2017-06-15 21:59-0500","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","PO-Revision-Date":"2017-06-25 09:38-0400","Last-Translator":"Copied by Zanata ","Language-Team":"Portuguese (Brazil)","Language":"pt-BR","X-Generator":"Zanata 3.9.6","Plural-Forms":"nplurals=2; plural=(n != 1)","lang":"pt_BR","domain":"app","plural_forms":"nplurals=2; plural=(n != 1)"},"%{commit_author_link} committed %{commit_timeago}":["%{commit_author_link} fez commit %{commit_timeago}"],"About auto deploy":["Sobre a implantação automática"],"Active":["Ativo"],"Activity":["Atividade"],"Add Changelog":["Adicionar registro de mudanças"],"Add Contribution guide":["Adicionar Guia de contribuição"],"Add License":["Adicionar Licença"],"Add an SSH key to your profile to pull or push via SSH.":["Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH."],"Add new directory":["Adicionar novo diretório"],"Archived project! Repository is read-only":["Projeto arquivado! O repositório é somente leitura"],"Are you sure you want to delete this pipeline schedule?":["Tem certeza que deseja excluir este agendamento de pipeline?"],"Attach a file by drag & drop or %{upload_link}":["Para anexar arquivo, arraste e solte ou %{upload_link}"],"Branch":["Branch","Branches"],"Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}":["O branch %{branch_name} foi criado. Para configurar a implantação automática, selecione um modelo de Yaml do GitLab CI e registre suas mudanças. %{link_to_autodeploy_doc}"],"Branches":["Branches"],"Browse files":["Navegar pelos arquivos"],"ByAuthor|by":["ByAuthor|por"],"CI configuration":["Configuração da Integração Contínua"],"Cancel":["Cancelar"],"ChangeTypeActionLabel|Pick into branch":["ChangeTypeActionLabel|Pick para um branch"],"ChangeTypeActionLabel|Revert in branch":["ChangeTypeActionLabel|Reverter no branch"],"ChangeTypeAction|Cherry-pick":["ChangeTypeAction|Cherry-pick"],"ChangeTypeAction|Revert":["ChangeTypeAction|Reverter"],"Changelog":["Registro de mudanças"],"Charts":["Gráficos"],"Cherry-pick this commit":["Cherry-pick esse commit"],"Cherry-pick this merge request":["Cherry-pick esse merge request"],"CiStatusLabel|canceled":["CiStatusLabel|cancelado"],"CiStatusLabel|created":["CiStatusLabel|criado"],"CiStatusLabel|failed":["CiStatusLabel|falhou"],"CiStatusLabel|manual action":["CiStatusLabel|ação manual"],"CiStatusLabel|passed":["CiStatusLabel|passou"],"CiStatusLabel|passed with warnings":["CiStatusLabel|passou com avisos"],"CiStatusLabel|pending":["CiStatusLabel|pendente"],"CiStatusLabel|skipped":["CiStatusLabel|ignorado"],"CiStatusLabel|waiting for manual action":["CiStatusLabel|aguardando ação manual"],"CiStatusText|blocked":["CiStatusText|bloqueado"],"CiStatusText|canceled":["CiStatusText|cancelado"],"CiStatusText|created":["CiStatusText|criado"],"CiStatusText|failed":["CiStatusText|falhou"],"CiStatusText|manual":["CiStatusText|manual"],"CiStatusText|passed":["CiStatusText|passou"],"CiStatusText|pending":["CiStatusText|pendente"],"CiStatusText|skipped":["CiStatusText|ignorado"],"CiStatus|running":["CiStatus|executando"],"Commit":["Commit","Commits"],"Commit message":["Mensagem de commit"],"CommitBoxTitle|Commit":["CommitBoxTitle|Commit"],"CommitMessage|Add %{file_name}":["CommitMessage|Adicionar %{file_name}"],"Commits":["Commits"],"Commits|History":["Commits|Histórico"],"Committed by":["Commit feito por"],"Compare":["Comparar"],"Contribution guide":["Guia de contribuição"],"Contributors":["Contribuidores"],"Copy URL to clipboard":["Copiar URL para área de transferência"],"Copy commit SHA to clipboard":["Copiar SHA do commit para a área de transferência"],"Create New Directory":["Criar Novo Diretório"],"Create directory":["Criar diretório"],"Create empty bare repository":["Criar repositório bruto vazio"],"Create merge request":["Criar merge request"],"Create new...":["Criar novo..."],"CreateNewFork|Fork":["CreateNewFork|Fork"],"CreateTag|Tag":["CreateTag|Tag"],"Cron Timezone":["Fuso horário do cron"],"Cron syntax":["Sintaxe do cron"],"Custom notification events":["Eventos de notificação personalizados"],"Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}.":["Níveis de notificação personalizados são equivalentes a níveis de participação. Com níveis de notificação personalizados você também será notificado sobre eventos selecionados. Para mais informações, visite %{notification_link}."],"Cycle Analytics":["Análise de Ciclo"],"Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.":["A Análise de Ciclo fornece uma visão geral de quanto tempo uma ideia demora para ir para produção em seu projeto."],"CycleAnalyticsStage|Code":["CycleAnalyticsStage|Código"],"CycleAnalyticsStage|Issue":["CycleAnalyticsStage|Issue"],"CycleAnalyticsStage|Plan":["CycleAnalyticsStage|Plano"],"CycleAnalyticsStage|Production":["CycleAnalyticsStage|Produção"],"CycleAnalyticsStage|Review":["CycleAnalyticsStage|Revisão"],"CycleAnalyticsStage|Staging":["CycleAnalyticsStage|Homologação"],"CycleAnalyticsStage|Test":["CycleAnalyticsStage|Teste"],"Define a custom pattern with cron syntax":["Defina um padrão personalizado utilizando a sintaxe do cron"],"Delete":["Excluir"],"Deploy":["Implantação","Implantações"],"Description":["Descrição"],"Directory name":["Nome do diretório"],"Don't show again":["Não exibir novamente"],"Download":["Baixar"],"Download tar":["Baixar tar"],"Download tar.bz2":["Baixar tar.bz2"],"Download tar.gz":["Baixar tar.gz"],"Download zip":["Baixar zip"],"DownloadArtifacts|Download":["DownloadArtifacts|Baixar"],"DownloadCommit|Email Patches":["DownloadCommit|Email com as mudanças"],"DownloadCommit|Plain Diff":["DownloadCommit|Arquivo de texto com as mudanças"],"DownloadSource|Download":["DownloadSource|Baixar"],"Edit":["Alterar"],"Edit Pipeline Schedule %{id}":["Alterar Agendamento do Pipeline %{id}"],"Every day (at 4:00am)":["Todos os dias (às 4:00)"],"Every month (on the 1st at 4:00am)":["Todos os meses (no dia primeiro às 4:00)"],"Every week (Sundays at 4:00am)":["Toda semana (domingos às 4:00)"],"Failed to change the owner":["Erro ao alterar o proprietário"],"Failed to remove the pipeline schedule":["Erro ao excluir o agendamento do pipeline"],"Files":["Arquivos"],"Find by path":["Localizar por caminho"],"Find file":["Localizar arquivo"],"FirstPushedBy|First":["FirstPushedBy|Primeiro"],"FirstPushedBy|pushed by":["FirstPushedBy|publicado por"],"Fork":["Fork","Forks"],"ForkedFromProjectPath|Forked from":["ForkedFromProjectPath|Forked de"],"From issue creation until deploy to production":["Da abertura de tarefas até a implantação para a produção"],"From merge request merge until deploy to production":["Da aceitação da solicitação de incorporação até a implantação em produção"],"Go to your fork":["Ir para seu fork"],"GoToYourFork|Fork":["GoToYourFork|Fork"],"Home":["Início"],"Housekeeping successfully started":["Manutenção iniciada com sucesso"],"Import repository":["Importar repositório"],"Interval Pattern":["Padrão de intervalo"],"Introducing Cycle Analytics":["Apresentando a Análise de Ciclo"],"LFSStatus|Disabled":["LFSStatus|Desabilitado"],"LFSStatus|Enabled":["LFSStatus|Habilitado"],"Last %d day":["Último %d dia","Últimos %d dias"],"Last Pipeline":["Último Pipeline"],"Last Update":["Última Atualização"],"Last commit":["Último commit"],"Learn more in the":["Saiba mais em"],"Learn more in the|pipeline schedules documentation":["Learn more in the|documentação de agendamento de pipeline"],"Leave group":["Sair do grupo"],"Leave project":["Sair do projeto"],"Limited to showing %d event at most":["Limitado a mostrar %d evento, no máximo","Limitado a mostrar %d eventos, no máximo"],"Median":["Mediana"],"MissingSSHKeyWarningLink|add an SSH key":["MissingSSHKeyWarningLink|adicione uma chave SSH"],"New Issue":["Nova Issue","Novas Issues"],"New Pipeline Schedule":["Novo Agendamento de Pipeline"],"New branch":["Novo branch"],"New directory":["Novo diretório"],"New file":["Novo arquivo"],"New issue":["Nova issue"],"New merge request":["Novo merge request"],"New schedule":["Novo agendamento"],"New snippet":["Novo snippet"],"New tag":["Nova tag"],"No repository":["Nenhum repositório"],"No schedules":["Nenhum agendamento"],"Not available":["Não disponível"],"Not enough data":["Dados insuficientes"],"Notification events":["Eventos de notificação"],"NotificationEvent|Close issue":["NotificationEvent|Fechar issue"],"NotificationEvent|Close merge request":["NotificationEvent|Fechar merge request"],"NotificationEvent|Failed pipeline":["NotificationEvent|Falha no pipeline"],"NotificationEvent|Merge merge request":["NotificationEvent|Aceitar merge request"],"NotificationEvent|New issue":["NotificationEvent|Nova issue"],"NotificationEvent|New merge request":["NotificationEvent|Novo merge request"],"NotificationEvent|New note":["NotificationEvent|Novo comentário"],"NotificationEvent|Reassign issue":["NotificationEvent|Reatribuir issue"],"NotificationEvent|Reassign merge request":["NotificationEvent|Reatribuir merge request"],"NotificationEvent|Reopen issue":["NotificationEvent|Reabrir issue"],"NotificationEvent|Successful pipeline":["NotificationEvent|Pipeline bem sucedido"],"NotificationLevel|Custom":["NotificationLevel|Personalizar"],"NotificationLevel|Disabled":["NotificationLevel|Desabilitado"],"NotificationLevel|Global":["NotificationLevel|Global"],"NotificationLevel|On mention":["NotificationLevel|Quando mencionado"],"NotificationLevel|Participate":["NotificationLevel|Participar"],"NotificationLevel|Watch":["NotificationLevel|Observar"],"OfSearchInADropdown|Filter":["OfSearchInADropdown|Filtrar"],"OpenedNDaysAgo|Opened":["OpenedNDaysAgo|Aberto"],"Options":["Opções"],"Owner":["Proprietário"],"Pipeline":["Pipeline"],"Pipeline Health":["Saúde da Pipeline"],"Pipeline Schedule":["Agendamento da Pipeline"],"Pipeline Schedules":["Agendamentos da Pipeline"],"PipelineSchedules|Activated":["PipelineSchedules|Ativado"],"PipelineSchedules|Active":["PipelineSchedules|Ativo"],"PipelineSchedules|All":["PipelineSchedules|Todos"],"PipelineSchedules|Inactive":["PipelineSchedules|Inativo"],"PipelineSchedules|Next Run":["PipelineSchedules|Próxima Execução"],"PipelineSchedules|None":["PipelineSchedules|Nenhum"],"PipelineSchedules|Provide a short description for this pipeline":["PipelineSchedules|Digite uma descrição curta para esta pipeline"],"PipelineSchedules|Take ownership":["PipelineSchedules|Tornar-se proprietário"],"PipelineSchedules|Target":["PipelineSchedules|Destino"],"PipelineSheduleIntervalPattern|Custom":["PipelineSheduleIntervalPattern|Personalizado"],"Pipeline|with stage":["Pipeline|com etapa"],"Pipeline|with stages":["Pipeline|com etapas"],"Project '%{project_name}' queued for deletion.":["Projeto'%{project_name}' marcado para exclusão."],"Project '%{project_name}' was successfully created.":["Projeto '%{project_name}' criado com sucesso."],"Project '%{project_name}' was successfully updated.":["Projeto '%{project_name}' atualizado com sucesso."],"Project '%{project_name}' will be deleted.":["Projeto '%{project_name}' será excluído."],"Project access must be granted explicitly to each user.":["Acesso ao projeto deve ser concedido explicitamente para cada usuário."],"Project export could not be deleted.":["A exportação do projeto não pôde ser excluída."],"Project export has been deleted.":["Exportação do projeto excluída."],"Project export link has expired. Please generate a new export from your project settings.":["O link para a exportação do projeto expirou. Favor gerar uma nova exportação a partir das configurações do projeto."],"Project export started. A download link will be sent by email.":["Exportação do projeto iniciada. Um link para baixá-la será enviado por email."],"Project home":["Página inicial do projeto"],"ProjectFeature|Disabled":["ProjectFeature|Desabilitado"],"ProjectFeature|Everyone with access":["ProjectFeature|Todos que possuem acesso"],"ProjectFeature|Only team members":["ProjectFeature|Apenas membros do time"],"ProjectFileTree|Name":["ProjectFileTree|Nome"],"ProjectLastActivity|Never":["ProjectLastActivity|Nunca"],"ProjectLifecycle|Stage":["PipelineSchedules|Etapa"],"ProjectNetworkGraph|Graph":["ProjectNetworkGraph|Árvore"],"Read more":["Leia mais"],"Readme":["Leia-me"],"RefSwitcher|Branches":["RefSwitcher|Branches"],"RefSwitcher|Tags":["RefSwitcher|Tags"],"Related Commits":["Commits Relacionados"],"Related Deployed Jobs":["Tarefas Implantadas Relacionadas"],"Related Issues":["Issues Relacionadas"],"Related Jobs":["Tarefas Relacionadas"],"Related Merge Requests":["Merge Requests Relacionados"],"Related Merged Requests":["Merge Requests Relacionados"],"Remind later":["Lembrar mais tarde"],"Remove project":["Remover projeto"],"Request Access":["Solicitar acesso"],"Revert this commit":["Reverter este commit"],"Revert this merge request":["Reverter esse merge request"],"Save pipeline schedule":["Salvar agendamento da pipeline"],"Schedule a new pipeline":["Agendar nova pipeline"],"Scheduling Pipelines":["Agendando pipelines"],"Search branches and tags":["Procurar branch e tags"],"Select Archive Format":["Selecionar Formato do Arquivo"],"Select a timezone":["Selecionar fuso horário"],"Select target branch":["Selecionar branch de destino"],"Set a password on your account to pull or push via %{protocol}":["Defina uma senha para sua conta para aceitar ou entregar código via %{protocol}"],"Set up CI":["Configurar CI"],"Set up Koding":["Configurar Koding"],"Set up auto deploy":["Configurar implantação automática"],"SetPasswordToCloneLink|set a password":["SetPasswordToCloneLink|defina uma senha"],"Showing %d event":["Mostrando %d evento","Mostrando %d eventos"],"Source code":["Código-fonte"],"StarProject|Star":["StarProject|Marcar"],"Start a %{new_merge_request} with these changes":["Iniciar um %{new_merge_request} a partir dessas alterações"],"Switch branch/tag":["Trocar branch/tag"],"Tag":["Tag","Tags"],"Tags":["Tags"],"Target Branch":["Branch de destino"],"The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.":["A etapa de codificação mostra o tempo desde a entrega do primeiro commit até a criação do merge request. Os dados serão automaticamente adicionados aqui desde o momento de criação do merge request."],"The collection of events added to the data gathered for that stage.":["A coleção de eventos adicionados aos dados coletados para essa etapa."],"The fork relationship has been removed.":["O relacionamento como fork foi removido."],"The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.":["A etapa de relatos mostra o tempo que leva desde a criação de uma issue até sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. Comece a criar issues para ver dados para esta etapa."],"The phase of the development lifecycle.":["A fase do ciclo de vida do desenvolvimento."],"The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.":["O agendamento de pipeline executa pipelines no futuro, repetidamente, para branches ou tags específicas. Essas pipelines agendadas terão acesso limitado ao projeto baseado no seu usuário associado."],"The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.":["A etapa de planejamento mostra o tempo do passo anterior até a publicação de seu primeiro conjunto de mudanças. Este tempo será adicionado automaticamente assim que você enviar seu primeiro conjunto de mudanças."],"The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.":["A etapa de produção mostra o tempo total que leva entre criar uma issue e implantar o código em produção. Os dados serão adicionados automaticamente assim que você completar todo o ciclo de produção."],"The project can be accessed by any logged in user.":["O projeto pode ser acessado por qualquer usuário autenticado."],"The project can be accessed without any authentication.":["O projeto pode ser acessado sem a necessidade de autenticação."],"The repository for this project does not exist.":["Não existe repositório para este projeto."],"The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.":["A etapa de revisão mostra o tempo de criação de uma solicitação de incorporação até sua aceitação. Os dados serão automaticamente adicionados depois que sua primeira solicitação de incorporação for aceita."],"The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.":["A etapa de homologação mostra o tempo entre o aceite da solicitação de incorporação e a implantação do código no ambiente de produção. Os dados serão automaticamente adicionados depois que você implantar em produção pela primeira vez."],"The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.":["A etapa de testes mostra o tempo que o GitLab CI leva para executar cada pipeline para a solicitação de incorporação associada. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."],"The time taken by each data entry gathered by that stage.":["O tempo necessário por cada entrada de dados reunida por essa etapa."],"The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6.":["O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."],"This means you can not push code until you create an empty repository or import existing one.":["Isto significa que você não pode entregar código até que crie um repositório vazio ou importe um existente."],"Time before an issue gets scheduled":["Tempo até que uma issue seja agendada"],"Time before an issue starts implementation":["Tempo até que uma issue comece a ser implementado"],"Time between merge request creation and merge/close":["Tempo entre a criação da solicitação de incorporação e a aceitação/fechamento"],"Time until first merge request":["Tempo até a primeira solicitação de incorporação"],"Timeago|%s days ago":["Timeago|há %s dias"],"Timeago|%s days remaining":["Timeago|%s dias restantes"],"Timeago|%s hours remaining":["Timeago|%s horas restantes"],"Timeago|%s minutes ago":["Timeago|há %s minutos"],"Timeago|%s minutes remaining":["Timeago|%s minutos restantes"],"Timeago|%s months ago":["Timeago|há %s meses"],"Timeago|%s months remaining":["Timeago|%s meses restantes"],"Timeago|%s seconds remaining":["Timeago|%s segundos restantes"],"Timeago|%s weeks ago":["Timeago|há %s semanas"],"Timeago|%s weeks remaining":["Timeago|%s semanas restantes"],"Timeago|%s years ago":["Timeago|há %s anos"],"Timeago|%s years remaining":["Timeago|%s anos restantes"],"Timeago|1 day remaining":["Timeago|1 dia restante"],"Timeago|1 hour remaining":["Timeago|1 hora restante"],"Timeago|1 minute remaining":["Timeago|1 minuto restante"],"Timeago|1 month remaining":["Timeago|1 mês restante"],"Timeago|1 week remaining":["Timeago|1 semana restante"],"Timeago|1 year remaining":["Timeago|1 ano restante"],"Timeago|Past due":["Timeago|Venceu"],"Timeago|a day ago":["Timeago|há um dia"],"Timeago|a month ago":["Timeago|há um mês"],"Timeago|a week ago":["Timeago|há uma semana"],"Timeago|a while":["Timeago|há algum tempo"],"Timeago|a year ago":["Timeago|há um ano"],"Timeago|about %s hours ago":["Timeago|há cerca de %s horas"],"Timeago|about a minute ago":["Timeago|há cerca de um minuto"],"Timeago|about an hour ago":["Timeago|há cerca de uma hora"],"Timeago|in %s days":["Timeago|em %s dias"],"Timeago|in %s hours":["Timeago|em %s horas"],"Timeago|in %s minutes":["Timeago|em %s minutos"],"Timeago|in %s months":["Timeago|em %s meses"],"Timeago|in %s seconds":["Timeago|em %s segundos"],"Timeago|in %s weeks":["Timeago|em %s semanas"],"Timeago|in %s years":["Timeago|em %s anos"],"Timeago|in 1 day":["Timeago|em 1 dia"],"Timeago|in 1 hour":["Timeago|em 1 hora"],"Timeago|in 1 minute":["Timeago|em 1 minuto"],"Timeago|in 1 month":["Timeago|em 1 mês"],"Timeago|in 1 week":["Timeago|em 1 semana"],"Timeago|in 1 year":["Timeago|em 1 ano"],"Timeago|less than a minute ago":["Timeago|há menos de um minuto"],"Time|hr":["Time|h","Time|hs"],"Time|min":["Time|min","Time|mins"],"Time|s":["Time|s"],"Total Time":["Tempo Total"],"Total test time for all commits/merges":["Tempo de teste total para todos os commits/merges"],"Unstar":["Desmarcar"],"Upload New File":["Enviar Novo Arquivo"],"Upload file":["Enviar arquivo"],"Use your global notification setting":["Utilizar configuração de notificação global"],"VisibilityLevel|Internal":["VisibilityLevel|Interno"],"VisibilityLevel|Private":["VisibilityLevel|Privado"],"VisibilityLevel|Public":["VisibilityLevel|Público"],"Want to see the data? Please ask an administrator for access.":["Precisa visualizar os dados? Solicite acesso ao administrador."],"We don't have enough data to show this stage.":["Esta etapa não possui dados suficientes para exibição."],"Withdraw Access Request":["Remover Requisição de Acesso"],"You are going to remove %{project_name_with_namespace}.\\nRemoved project CANNOT be restored!\\nAre you ABSOLUTELY sure?":["Você irá remover %{project_name_with_namespace}.\\nO projeto removido NÃO PODE ser restaurado!\\nTem certeza ABSOLUTA?"],"You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?":["Você ira remover o relacionamento de fork com o projeto original %{forked_from_project}. Tem certeza ABSOLUTA?"],"You are going to transfer %{project_name_with_namespace} to another owner. Are you ABSOLUTELY sure?":["Você irá transferir %{project_name_with_namespace} para outro proprietário. Tem certeza ABSOLUTA?"],"You can only add files when you are on a branch":["Você somente pode adicionar arquivos quando estiver em um branch"],"You have reached your project limit":["Você atingiu o limite de seu projeto"],"You must sign in to star a project":["Você deve estar autenticado para marcar um projeto"],"You need permission.":["Você precisa de permissão."],"You will not get any notifications via email":["Você não será notificado por email"],"You will only receive notifications for the events you choose":["Você será notificado apenas sobre eventos selecionados"],"You will only receive notifications for threads you have participated in":["Você será notificado apenas sobre tópicos nos quais participou"],"You will receive notifications for any activity":["Você será notificado sobre qualquer atividade"],"You will receive notifications only for comments in which you were @mentioned":["Você será notificado apenas sobre comentários que te @mencionam"],"You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account":["Você não poderá fazer pull ou push via %{protocol} até que %{set_password_link} para sua conta"],"You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile":["Você não conseguirá fazer pull ou push no projeto via SSH até que adicione %{add_ssh_key_link} ao seu perfil"],"Your name":["Seu nome"],"day":["dia","dias"],"new merge request":["novo merge request"],"notification emails":["emails de notificação"],"parent":["pai","pais"]}}}; \ No newline at end of file From 9ab0314e6f27e61cd257972c41b07bdb2535289a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 11:41:45 +0800 Subject: [PATCH 06/61] supplement portuguese brazil translation Fix #33672 --- ..._portuguese_brazil_translation_of_i18n.yml | 4 + locale/pt_BR/gitlab.po | 1004 +++++++++++++++-- 2 files changed, 944 insertions(+), 64 deletions(-) create mode 100644 changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml new file mode 100644 index 00000000000..d2bdc631d2a --- /dev/null +++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml @@ -0,0 +1,4 @@ +--- +title: Supplement Portuguese Brazil translation of Project Page & Repository Page +merge_request: 12156 +author: Huang Tao diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index fe6d51c36ac..6377ed36e48 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,29 +1,244 @@ -# Alexandre Alencar , 2017. #zanata # Fabio Beneditto , 2017. #zanata -# Leandro Nunes dos Santos , 2017. #zanata +# Huang Tao , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-05-04 19:24-0500\n" +"POT-Creation-Date: 2017-06-15 21:59-0500\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-05 03:29-0400\n" -"Last-Translator: Alexandre Alencar \n" +"PO-Revision-Date: 2017-06-25 09:38-0400\n" +"Last-Translator: Copied by Zanata \n" "Language-Team: Portuguese (Brazil)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +msgid "%{commit_author_link} committed %{commit_timeago}" +msgstr "%{commit_author_link} fez commit %{commit_timeago}" + +msgid "About auto deploy" +msgstr "Sobre a implantação automática" + +msgid "Active" +msgstr "Ativo" + +msgid "Activity" +msgstr "Atividade" + +msgid "Add Changelog" +msgstr "Adicionar registro de mudanças" + +msgid "Add Contribution guide" +msgstr "Adicionar Guia de contribuição" + +msgid "Add License" +msgstr "Adicionar Licença" + +msgid "Add an SSH key to your profile to pull or push via SSH." +msgstr "Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH." + +msgid "Add new directory" +msgstr "Adicionar novo diretório" + +msgid "Archived project! Repository is read-only" +msgstr "Projeto arquivado! O repositório é somente leitura" + +msgid "Are you sure you want to delete this pipeline schedule?" +msgstr "Tem certeza que deseja excluir este agendamento de pipeline?" + +msgid "Attach a file by drag & drop or %{upload_link}" +msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}" + +msgid "Branch" +msgid_plural "Branches" +msgstr[0] "Branch" +msgstr[1] "Branches" + +msgid "" +"Branch %{branch_name} was created. To set up auto deploy, " +"choose a GitLab CI Yaml template and commit your changes. " +"%{link_to_autodeploy_doc}" +msgstr "" +"O branch %{branch_name} foi criado. Para configurar a " +"implantação automática, selecione um modelo de Yaml do GitLab CI e registre " +"suas mudanças. %{link_to_autodeploy_doc}" + +msgid "Branches" +msgstr "Branches" + +msgid "Browse files" +msgstr "Navegar pelos arquivos" + msgid "ByAuthor|by" -msgstr "por" +msgstr "ByAuthor|por" + +msgid "CI configuration" +msgstr "Configuração da Integração Contínua" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "ChangeTypeActionLabel|Pick into branch" +msgstr "ChangeTypeActionLabel|Pick para um branch" + +msgid "ChangeTypeActionLabel|Revert in branch" +msgstr "ChangeTypeActionLabel|Reverter no branch" + +msgid "ChangeTypeAction|Cherry-pick" +msgstr "ChangeTypeAction|Cherry-pick" + +msgid "ChangeTypeAction|Revert" +msgstr "ChangeTypeAction|Reverter" + +msgid "Changelog" +msgstr "Registro de mudanças" + +msgid "Charts" +msgstr "Gráficos" + +msgid "Cherry-pick this commit" +msgstr "Cherry-pick esse commit" + +msgid "Cherry-pick this merge request" +msgstr "Cherry-pick esse merge request" + +msgid "CiStatusLabel|canceled" +msgstr "CiStatusLabel|cancelado" + +msgid "CiStatusLabel|created" +msgstr "CiStatusLabel|criado" + +msgid "CiStatusLabel|failed" +msgstr "CiStatusLabel|falhou" + +msgid "CiStatusLabel|manual action" +msgstr "CiStatusLabel|ação manual" + +msgid "CiStatusLabel|passed" +msgstr "CiStatusLabel|passou" + +msgid "CiStatusLabel|passed with warnings" +msgstr "CiStatusLabel|passou com avisos" + +msgid "CiStatusLabel|pending" +msgstr "CiStatusLabel|pendente" + +msgid "CiStatusLabel|skipped" +msgstr "CiStatusLabel|ignorado" + +msgid "CiStatusLabel|waiting for manual action" +msgstr "CiStatusLabel|aguardando ação manual" + +msgid "CiStatusText|blocked" +msgstr "CiStatusText|bloqueado" + +msgid "CiStatusText|canceled" +msgstr "CiStatusText|cancelado" + +msgid "CiStatusText|created" +msgstr "CiStatusText|criado" + +msgid "CiStatusText|failed" +msgstr "CiStatusText|falhou" + +msgid "CiStatusText|manual" +msgstr "CiStatusText|manual" + +msgid "CiStatusText|passed" +msgstr "CiStatusText|passou" + +msgid "CiStatusText|pending" +msgstr "CiStatusText|pendente" + +msgid "CiStatusText|skipped" +msgstr "CiStatusText|ignorado" + +msgid "CiStatus|running" +msgstr "CiStatus|executando" msgid "Commit" msgid_plural "Commits" msgstr[0] "Commit" msgstr[1] "Commits" +msgid "Commit message" +msgstr "Mensagem de commit" + +msgid "CommitBoxTitle|Commit" +msgstr "CommitBoxTitle|Commit" + +msgid "CommitMessage|Add %{file_name}" +msgstr "CommitMessage|Adicionar %{file_name}" + +msgid "Commits" +msgstr "Commits" + +msgid "Commits|History" +msgstr "Commits|Histórico" + +msgid "Committed by" +msgstr "Commit feito por" + +msgid "Compare" +msgstr "Comparar" + +msgid "Contribution guide" +msgstr "Guia de contribuição" + +msgid "Contributors" +msgstr "Contribuidores" + +msgid "Copy URL to clipboard" +msgstr "Copiar URL para área de transferência" + +msgid "Copy commit SHA to clipboard" +msgstr "Copiar SHA do commit para a área de transferência" + +msgid "Create New Directory" +msgstr "Criar Novo Diretório" + +msgid "Create directory" +msgstr "Criar diretório" + +msgid "Create empty bare repository" +msgstr "Criar repositório bruto vazio" + +msgid "Create merge request" +msgstr "Criar merge request" + +msgid "Create new..." +msgstr "Criar novo..." + +msgid "CreateNewFork|Fork" +msgstr "CreateNewFork|Fork" + +msgid "CreateTag|Tag" +msgstr "CreateTag|Tag" + +msgid "Cron Timezone" +msgstr "Fuso horário do cron" + +msgid "Cron syntax" +msgstr "Sintaxe do cron" + +msgid "Custom notification events" +msgstr "Eventos de notificação personalizados" + +msgid "" +"Custom notification levels are the same as participating levels. With custom " +"notification levels you will also receive notifications for select events. " +"To find out more, check out %{notification_link}." +msgstr "" +"Níveis de notificação personalizados são equivalentes a níveis de " +"participação. Com níveis de notificação personalizados você também será " +"notificado sobre eventos selecionados. Para mais informações, visite " +"%{notification_link}." + +msgid "Cycle Analytics" +msgstr "Análise de Ciclo" + msgid "" "Cycle Analytics gives an overview of how much time it takes to go from idea " "to production in your project." @@ -32,63 +247,225 @@ msgstr "" "para ir para produção em seu projeto." msgid "CycleAnalyticsStage|Code" -msgstr "Código" +msgstr "CycleAnalyticsStage|Código" msgid "CycleAnalyticsStage|Issue" -msgstr "Tarefa" +msgstr "CycleAnalyticsStage|Issue" msgid "CycleAnalyticsStage|Plan" -msgstr "Plano" +msgstr "CycleAnalyticsStage|Plano" msgid "CycleAnalyticsStage|Production" -msgstr "Produção" +msgstr "CycleAnalyticsStage|Produção" msgid "CycleAnalyticsStage|Review" -msgstr "Revisão" +msgstr "CycleAnalyticsStage|Revisão" msgid "CycleAnalyticsStage|Staging" -msgstr "Homologação" +msgstr "CycleAnalyticsStage|Homologação" msgid "CycleAnalyticsStage|Test" -msgstr "Teste" +msgstr "CycleAnalyticsStage|Teste" + +msgid "Define a custom pattern with cron syntax" +msgstr "Defina um padrão personalizado utilizando a sintaxe do cron" + +msgid "Delete" +msgstr "Excluir" msgid "Deploy" msgid_plural "Deploys" msgstr[0] "Implantação" msgstr[1] "Implantações" +msgid "Description" +msgstr "Descrição" + +msgid "Directory name" +msgstr "Nome do diretório" + +msgid "Don't show again" +msgstr "Não exibir novamente" + +msgid "Download" +msgstr "Baixar" + +msgid "Download tar" +msgstr "Baixar tar" + +msgid "Download tar.bz2" +msgstr "Baixar tar.bz2" + +msgid "Download tar.gz" +msgstr "Baixar tar.gz" + +msgid "Download zip" +msgstr "Baixar zip" + +msgid "DownloadArtifacts|Download" +msgstr "DownloadArtifacts|Baixar" + +msgid "DownloadCommit|Email Patches" +msgstr "DownloadCommit|Email com as mudanças" + +msgid "DownloadCommit|Plain Diff" +msgstr "DownloadCommit|Arquivo de texto com as mudanças" + +msgid "DownloadSource|Download" +msgstr "DownloadSource|Baixar" + +msgid "Edit" +msgstr "Alterar" + +msgid "Edit Pipeline Schedule %{id}" +msgstr "Alterar Agendamento do Pipeline %{id}" + +msgid "Every day (at 4:00am)" +msgstr "Todos os dias (às 4:00)" + +msgid "Every month (on the 1st at 4:00am)" +msgstr "Todos os meses (no dia primeiro às 4:00)" + +msgid "Every week (Sundays at 4:00am)" +msgstr "Toda semana (domingos às 4:00)" + +msgid "Failed to change the owner" +msgstr "Erro ao alterar o proprietário" + +msgid "Failed to remove the pipeline schedule" +msgstr "Erro ao excluir o agendamento do pipeline" + +msgid "Files" +msgstr "Arquivos" + +msgid "Find by path" +msgstr "Localizar por caminho" + +msgid "Find file" +msgstr "Localizar arquivo" + msgid "FirstPushedBy|First" -msgstr "Primeiro" +msgstr "FirstPushedBy|Primeiro" msgid "FirstPushedBy|pushed by" -msgstr "publicado por" +msgstr "FirstPushedBy|publicado por" + +msgid "Fork" +msgid_plural "Forks" +msgstr[0] "Fork" +msgstr[1] "Forks" + +msgid "ForkedFromProjectPath|Forked from" +msgstr "ForkedFromProjectPath|Forked de" msgid "From issue creation until deploy to production" -msgstr "Da criação de tarefas até a implantação para a produção" +msgstr "Da abertura de tarefas até a implantação para a produção" msgid "From merge request merge until deploy to production" -msgstr "Da incorporação do merge request até a implantação em produção" +msgstr "" +"Da aceitação da solicitação de incorporação até a implantação em produção" + +msgid "Go to your fork" +msgstr "Ir para seu fork" + +msgid "GoToYourFork|Fork" +msgstr "GoToYourFork|Fork" + +msgid "Home" +msgstr "Início" + +msgid "Housekeeping successfully started" +msgstr "Manutenção iniciada com sucesso" + +msgid "Import repository" +msgstr "Importar repositório" + +msgid "Interval Pattern" +msgstr "Padrão de intervalo" msgid "Introducing Cycle Analytics" msgstr "Apresentando a Análise de Ciclo" +msgid "LFSStatus|Disabled" +msgstr "LFSStatus|Desabilitado" + +msgid "LFSStatus|Enabled" +msgstr "LFSStatus|Habilitado" + msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "Último %d dia" msgstr[1] "Últimos %d dias" +msgid "Last Pipeline" +msgstr "Último Pipeline" + +msgid "Last Update" +msgstr "Última Atualização" + +msgid "Last commit" +msgstr "Último commit" + +msgid "Learn more in the" +msgstr "Saiba mais em" + +msgid "Learn more in the|pipeline schedules documentation" +msgstr "Learn more in the|documentação de agendamento de pipeline" + +msgid "Leave group" +msgstr "Sair do grupo" + +msgid "Leave project" +msgstr "Sair do projeto" + msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" -msgstr[0] "Limitado a mostrar %d evento no máximo" -msgstr[1] "Limitado a mostrar %d eventos no máximo" +msgstr[0] "Limitado a mostrar %d evento, no máximo" +msgstr[1] "Limitado a mostrar %d eventos, no máximo" msgid "Median" msgstr "Mediana" +msgid "MissingSSHKeyWarningLink|add an SSH key" +msgstr "MissingSSHKeyWarningLink|adicione uma chave SSH" + msgid "New Issue" msgid_plural "New Issues" -msgstr[0] "Nova Tarefa" -msgstr[1] "Novas Tarefas" +msgstr[0] "Nova Issue" +msgstr[1] "Novas Issues" + +msgid "New Pipeline Schedule" +msgstr "Novo Agendamento de Pipeline" + +msgid "New branch" +msgstr "Novo branch" + +msgid "New directory" +msgstr "Novo diretório" + +msgid "New file" +msgstr "Novo arquivo" + +msgid "New issue" +msgstr "Nova issue" + +msgid "New merge request" +msgstr "Novo merge request" + +msgid "New schedule" +msgstr "Novo agendamento" + +msgid "New snippet" +msgstr "Novo snippet" + +msgid "New tag" +msgstr "Nova tag" + +msgid "No repository" +msgstr "Nenhum repositório" + +msgid "No schedules" +msgstr "Nenhum agendamento" msgid "Not available" msgstr "Não disponível" @@ -96,29 +473,201 @@ msgstr "Não disponível" msgid "Not enough data" msgstr "Dados insuficientes" +msgid "Notification events" +msgstr "Eventos de notificação" + +msgid "NotificationEvent|Close issue" +msgstr "NotificationEvent|Fechar issue" + +msgid "NotificationEvent|Close merge request" +msgstr "NotificationEvent|Fechar merge request" + +msgid "NotificationEvent|Failed pipeline" +msgstr "NotificationEvent|Falha no pipeline" + +msgid "NotificationEvent|Merge merge request" +msgstr "NotificationEvent|Aceitar merge request" + +msgid "NotificationEvent|New issue" +msgstr "NotificationEvent|Nova issue" + +msgid "NotificationEvent|New merge request" +msgstr "NotificationEvent|Novo merge request" + +msgid "NotificationEvent|New note" +msgstr "NotificationEvent|Novo comentário" + +msgid "NotificationEvent|Reassign issue" +msgstr "NotificationEvent|Reatribuir issue" + +msgid "NotificationEvent|Reassign merge request" +msgstr "NotificationEvent|Reatribuir merge request" + +msgid "NotificationEvent|Reopen issue" +msgstr "NotificationEvent|Reabrir issue" + +msgid "NotificationEvent|Successful pipeline" +msgstr "NotificationEvent|Pipeline bem sucedido" + +msgid "NotificationLevel|Custom" +msgstr "NotificationLevel|Personalizar" + +msgid "NotificationLevel|Disabled" +msgstr "NotificationLevel|Desabilitado" + +msgid "NotificationLevel|Global" +msgstr "NotificationLevel|Global" + +msgid "NotificationLevel|On mention" +msgstr "NotificationLevel|Quando mencionado" + +msgid "NotificationLevel|Participate" +msgstr "NotificationLevel|Participar" + +msgid "NotificationLevel|Watch" +msgstr "NotificationLevel|Observar" + +msgid "OfSearchInADropdown|Filter" +msgstr "OfSearchInADropdown|Filtrar" + msgid "OpenedNDaysAgo|Opened" -msgstr "Aberto" +msgstr "OpenedNDaysAgo|Aberto" + +msgid "Options" +msgstr "Opções" + +msgid "Owner" +msgstr "Proprietário" + +msgid "Pipeline" +msgstr "Pipeline" msgid "Pipeline Health" msgstr "Saúde da Pipeline" +msgid "Pipeline Schedule" +msgstr "Agendamento da Pipeline" + +msgid "Pipeline Schedules" +msgstr "Agendamentos da Pipeline" + +msgid "PipelineSchedules|Activated" +msgstr "PipelineSchedules|Ativado" + +msgid "PipelineSchedules|Active" +msgstr "PipelineSchedules|Ativo" + +msgid "PipelineSchedules|All" +msgstr "PipelineSchedules|Todos" + +msgid "PipelineSchedules|Inactive" +msgstr "PipelineSchedules|Inativo" + +msgid "PipelineSchedules|Next Run" +msgstr "PipelineSchedules|Próxima Execução" + +msgid "PipelineSchedules|None" +msgstr "PipelineSchedules|Nenhum" + +msgid "PipelineSchedules|Provide a short description for this pipeline" +msgstr "PipelineSchedules|Digite uma descrição curta para esta pipeline" + +msgid "PipelineSchedules|Take ownership" +msgstr "PipelineSchedules|Tornar-se proprietário" + +msgid "PipelineSchedules|Target" +msgstr "PipelineSchedules|Destino" + +msgid "PipelineSheduleIntervalPattern|Custom" +msgstr "PipelineSheduleIntervalPattern|Personalizado" + +msgid "Pipeline|with stage" +msgstr "Pipeline|com etapa" + +msgid "Pipeline|with stages" +msgstr "Pipeline|com etapas" + +msgid "Project '%{project_name}' queued for deletion." +msgstr "Projeto'%{project_name}' marcado para exclusão." + +msgid "Project '%{project_name}' was successfully created." +msgstr "Projeto '%{project_name}' criado com sucesso." + +msgid "Project '%{project_name}' was successfully updated." +msgstr "Projeto '%{project_name}' atualizado com sucesso." + +msgid "Project '%{project_name}' will be deleted." +msgstr "Projeto '%{project_name}' será excluído." + +msgid "Project access must be granted explicitly to each user." +msgstr "" +"Acesso ao projeto deve ser concedido explicitamente para cada usuário." + +msgid "Project export could not be deleted." +msgstr "A exportação do projeto não pôde ser excluída." + +msgid "Project export has been deleted." +msgstr "Exportação do projeto excluída." + +msgid "" +"Project export link has expired. Please generate a new export from your " +"project settings." +msgstr "" +"O link para a exportação do projeto expirou. Favor gerar uma nova exportação " +"a partir das configurações do projeto." + +msgid "Project export started. A download link will be sent by email." +msgstr "" +"Exportação do projeto iniciada. Um link para baixá-la será enviado por email." +"" + +msgid "Project home" +msgstr "Página inicial do projeto" + +msgid "ProjectFeature|Disabled" +msgstr "ProjectFeature|Desabilitado" + +msgid "ProjectFeature|Everyone with access" +msgstr "ProjectFeature|Todos que possuem acesso" + +msgid "ProjectFeature|Only team members" +msgstr "ProjectFeature|Apenas membros do time" + +msgid "ProjectFileTree|Name" +msgstr "ProjectFileTree|Nome" + +msgid "ProjectLastActivity|Never" +msgstr "ProjectLastActivity|Nunca" + msgid "ProjectLifecycle|Stage" -msgstr "Etapa" +msgstr "PipelineSchedules|Etapa" + +msgid "ProjectNetworkGraph|Graph" +msgstr "ProjectNetworkGraph|Árvore" msgid "Read more" -msgstr "Ler mais" +msgstr "Leia mais" + +msgid "Readme" +msgstr "Leia-me" + +msgid "RefSwitcher|Branches" +msgstr "RefSwitcher|Branches" + +msgid "RefSwitcher|Tags" +msgstr "RefSwitcher|Tags" msgid "Related Commits" msgstr "Commits Relacionados" msgid "Related Deployed Jobs" -msgstr "Jobs Relacionados Incorporados" +msgstr "Tarefas Implantadas Relacionadas" msgid "Related Issues" -msgstr "Tarefas Relacionadas" +msgstr "Issues Relacionadas" msgid "Related Jobs" -msgstr "Jobs Relacionados" +msgstr "Tarefas Relacionadas" msgid "Related Merge Requests" msgstr "Merge Requests Relacionados" @@ -126,84 +675,180 @@ msgstr "Merge Requests Relacionados" msgid "Related Merged Requests" msgstr "Merge Requests Relacionados" +msgid "Remind later" +msgstr "Lembrar mais tarde" + +msgid "Remove project" +msgstr "Remover projeto" + +msgid "Request Access" +msgstr "Solicitar acesso" + +msgid "Revert this commit" +msgstr "Reverter este commit" + +msgid "Revert this merge request" +msgstr "Reverter esse merge request" + +msgid "Save pipeline schedule" +msgstr "Salvar agendamento da pipeline" + +msgid "Schedule a new pipeline" +msgstr "Agendar nova pipeline" + +msgid "Scheduling Pipelines" +msgstr "Agendando pipelines" + +msgid "Search branches and tags" +msgstr "Procurar branch e tags" + +msgid "Select Archive Format" +msgstr "Selecionar Formato do Arquivo" + +msgid "Select a timezone" +msgstr "Selecionar fuso horário" + +msgid "Select target branch" +msgstr "Selecionar branch de destino" + +msgid "Set a password on your account to pull or push via %{protocol}" +msgstr "" +"Defina uma senha para sua conta para aceitar ou entregar código via " +"%{protocol}" + +msgid "Set up CI" +msgstr "Configurar CI" + +msgid "Set up Koding" +msgstr "Configurar Koding" + +msgid "Set up auto deploy" +msgstr "Configurar implantação automática" + +msgid "SetPasswordToCloneLink|set a password" +msgstr "SetPasswordToCloneLink|defina uma senha" + msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "Mostrando %d evento" msgstr[1] "Mostrando %d eventos" +msgid "Source code" +msgstr "Código-fonte" + +msgid "StarProject|Star" +msgstr "StarProject|Marcar" + +msgid "Start a %{new_merge_request} with these changes" +msgstr "Iniciar um %{new_merge_request} a partir dessas alterações" + +msgid "Switch branch/tag" +msgstr "Trocar branch/tag" + +msgid "Tag" +msgid_plural "Tags" +msgstr[0] "Tag" +msgstr[1] "Tags" + +msgid "Tags" +msgstr "Tags" + +msgid "Target Branch" +msgstr "Branch de destino" + msgid "" "The coding stage shows the time from the first commit to creating the merge " "request. The data will automatically be added here once you create your " "first merge request." msgstr "" -"O estágio de codificação mostra o tempo desde o primeiro commit até a " -"criação do merge request. \n" -"Os dados serão automaticamente adicionados aqui uma vez que você tenha " -"criado seu primeiro merge request." +"A etapa de codificação mostra o tempo desde a entrega do primeiro commit até " +"a criação do merge request. Os dados serão automaticamente adicionados aqui " +"desde o momento de criação do merge request." msgid "The collection of events added to the data gathered for that stage." -msgstr "" -"A coleção de eventos adicionados aos dados coletados para esse estágio." +msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa." + +msgid "The fork relationship has been removed." +msgstr "O relacionamento como fork foi removido." msgid "" "The issue stage shows the time it takes from creating an issue to assigning " "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"O estágio em questão mostra o tempo que leva desde a criação de uma tarefa " -"até a sua assinatura para um milestone, ou a sua adição para a lista no seu " -"Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa." +"A etapa de relatos mostra o tempo que leva desde a criação de uma issue até " +"sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. " +"Comece a criar issues para ver dados para esta etapa." msgid "The phase of the development lifecycle." msgstr "A fase do ciclo de vida do desenvolvimento." +msgid "" +"The pipelines schedule runs pipelines in the future, repeatedly, for " +"specific branches or tags. Those scheduled pipelines will inherit limited " +"project access based on their associated user." +msgstr "" +"O agendamento de pipeline executa pipelines no futuro, repetidamente, para " +"branches ou tags específicas. Essas pipelines agendadas terão acesso " +"limitado ao projeto baseado no seu usuário associado." + msgid "" "The planning stage shows the time from the previous step to pushing your " "first commit. This time will be added automatically once you push your first " "commit." msgstr "" -"A fase de planejamento mostra o tempo do passo anterior até empurrar o seu " -"primeiro commit. Este tempo será adicionado automaticamente assim que você " -"realizar seu primeiro commit." +"A etapa de planejamento mostra o tempo do passo anterior até a publicação de " +"seu primeiro conjunto de mudanças. Este tempo será adicionado " +"automaticamente assim que você enviar seu primeiro conjunto de mudanças." msgid "" "The production stage shows the total time it takes between creating an issue " "and deploying the code to production. The data will be automatically added " "once you have completed the full idea to production cycle." msgstr "" -"O estágio de produção mostra o tempo total que leva entre criar uma tarefa e " -"implantar o código na produção. Os dados serão adicionados automaticamente " -"até que você complete todo o ciclo de produção." +"A etapa de produção mostra o tempo total que leva entre criar uma issue e " +"implantar o código em produção. Os dados serão adicionados automaticamente " +"assim que você completar todo o ciclo de produção." + +msgid "The project can be accessed by any logged in user." +msgstr "O projeto pode ser acessado por qualquer usuário autenticado." + +msgid "The project can be accessed without any authentication." +msgstr "O projeto pode ser acessado sem a necessidade de autenticação." + +msgid "The repository for this project does not exist." +msgstr "Não existe repositório para este projeto." msgid "" "The review stage shows the time from creating the merge request to merging " "it. The data will automatically be added after you merge your first merge " "request." msgstr "" -"A etapa de revisão mostra o tempo de criação de um merge request até que o " -"merge seja feito. Os dados serão automaticamente adicionados depois que você " -"fizer seu primeiro merge request." +"A etapa de revisão mostra o tempo de criação de uma solicitação de " +"incorporação até sua aceitação. Os dados serão automaticamente adicionados " +"depois que sua primeira solicitação de incorporação for aceita." msgid "" "The staging stage shows the time between merging the MR and deploying code " "to the production environment. The data will be automatically added once you " "deploy to production for the first time." msgstr "" -"O estágio de estágio mostra o tempo entre a fusão do MR e o código de " -"implantação para o ambiente de produção. Os dados serão automaticamente " -"adicionados depois de implantar na produção pela primeira vez." +"A etapa de homologação mostra o tempo entre o aceite da solicitação de " +"incorporação e a implantação do código no ambiente de produção. Os dados " +"serão automaticamente adicionados depois que você implantar em produção pela " +"primeira vez." msgid "" "The testing stage shows the time GitLab CI takes to run every pipeline for " "the related merge request. The data will automatically be added after your " "first pipeline finishes running." msgstr "" -"A fase de teste mostra o tempo que o GitLab CI leva para executar cada " -"pipeline para o merge request relacionado. Os dados serão automaticamente " -"adicionados após a conclusão do primeiro pipeline." +"A etapa de testes mostra o tempo que o GitLab CI leva para executar cada " +"pipeline para a solicitação de incorporação associada. Os dados serão " +"automaticamente adicionados após a conclusão do primeiro pipeline." msgid "The time taken by each data entry gathered by that stage." -msgstr "O tempo necessário para cada entrada de dados reunida por essa etapa." +msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa." msgid "" "The value lying at the midpoint of a series of observed values. E.g., " @@ -211,32 +856,164 @@ msgid "" " 6." msgstr "" "O valor situado no ponto médio de uma série de valores observados. Ex., " -"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6." +"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6." + +msgid "" +"This means you can not push code until you create an empty repository or " +"import existing one." +msgstr "" +"Isto significa que você não pode entregar código até que crie um repositório " +"vazio ou importe um existente." msgid "Time before an issue gets scheduled" -msgstr "Tempo até que uma tarefa seja planejada" +msgstr "Tempo até que uma issue seja agendada" msgid "Time before an issue starts implementation" -msgstr "Tempo até que uma tarefa comece a ser implementada" +msgstr "Tempo até que uma issue comece a ser implementado" msgid "Time between merge request creation and merge/close" -msgstr "Tempo entre a criação do merge request e o merge/fechamento" +msgstr "" +"Tempo entre a criação da solicitação de incorporação e a aceitação/" +"fechamento" msgid "Time until first merge request" -msgstr "Tempo até o primeiro merge request" +msgstr "Tempo até a primeira solicitação de incorporação" + +msgid "Timeago|%s days ago" +msgstr "Timeago|há %s dias" + +msgid "Timeago|%s days remaining" +msgstr "Timeago|%s dias restantes" + +msgid "Timeago|%s hours remaining" +msgstr "Timeago|%s horas restantes" + +msgid "Timeago|%s minutes ago" +msgstr "Timeago|há %s minutos" + +msgid "Timeago|%s minutes remaining" +msgstr "Timeago|%s minutos restantes" + +msgid "Timeago|%s months ago" +msgstr "Timeago|há %s meses" + +msgid "Timeago|%s months remaining" +msgstr "Timeago|%s meses restantes" + +msgid "Timeago|%s seconds remaining" +msgstr "Timeago|%s segundos restantes" + +msgid "Timeago|%s weeks ago" +msgstr "Timeago|há %s semanas" + +msgid "Timeago|%s weeks remaining" +msgstr "Timeago|%s semanas restantes" + +msgid "Timeago|%s years ago" +msgstr "Timeago|há %s anos" + +msgid "Timeago|%s years remaining" +msgstr "Timeago|%s anos restantes" + +msgid "Timeago|1 day remaining" +msgstr "Timeago|1 dia restante" + +msgid "Timeago|1 hour remaining" +msgstr "Timeago|1 hora restante" + +msgid "Timeago|1 minute remaining" +msgstr "Timeago|1 minuto restante" + +msgid "Timeago|1 month remaining" +msgstr "Timeago|1 mês restante" + +msgid "Timeago|1 week remaining" +msgstr "Timeago|1 semana restante" + +msgid "Timeago|1 year remaining" +msgstr "Timeago|1 ano restante" + +msgid "Timeago|Past due" +msgstr "Timeago|Venceu" + +msgid "Timeago|a day ago" +msgstr "Timeago|há um dia" + +msgid "Timeago|a month ago" +msgstr "Timeago|há um mês" + +msgid "Timeago|a week ago" +msgstr "Timeago|há uma semana" + +msgid "Timeago|a while" +msgstr "Timeago|há algum tempo" + +msgid "Timeago|a year ago" +msgstr "Timeago|há um ano" + +msgid "Timeago|about %s hours ago" +msgstr "Timeago|há cerca de %s horas" + +msgid "Timeago|about a minute ago" +msgstr "Timeago|há cerca de um minuto" + +msgid "Timeago|about an hour ago" +msgstr "Timeago|há cerca de uma hora" + +msgid "Timeago|in %s days" +msgstr "Timeago|em %s dias" + +msgid "Timeago|in %s hours" +msgstr "Timeago|em %s horas" + +msgid "Timeago|in %s minutes" +msgstr "Timeago|em %s minutos" + +msgid "Timeago|in %s months" +msgstr "Timeago|em %s meses" + +msgid "Timeago|in %s seconds" +msgstr "Timeago|em %s segundos" + +msgid "Timeago|in %s weeks" +msgstr "Timeago|em %s semanas" + +msgid "Timeago|in %s years" +msgstr "Timeago|em %s anos" + +msgid "Timeago|in 1 day" +msgstr "Timeago|em 1 dia" + +msgid "Timeago|in 1 hour" +msgstr "Timeago|em 1 hora" + +msgid "Timeago|in 1 minute" +msgstr "Timeago|em 1 minuto" + +msgid "Timeago|in 1 month" +msgstr "Timeago|em 1 mês" + +msgid "Timeago|in 1 week" +msgstr "Timeago|em 1 semana" + +msgid "Timeago|in 1 year" +msgstr "Timeago|em 1 ano" + +msgid "Timeago|less than a minute ago" +msgstr "Timeago|há menos de um minuto" msgid "Time|hr" msgid_plural "Time|hrs" -msgstr[0] "h" -msgstr[1] "hs" +msgstr[0] "Time|h" +msgstr[1] "Time|hs" msgid "Time|min" msgid_plural "Time|mins" -msgstr[0] "min" -msgstr[1] "mins" +msgstr[0] "Time|min" +msgstr[1] "Time|mins" msgid "Time|s" -msgstr "s" +msgstr "Time|s" msgid "Total Time" msgstr "Tempo Total" @@ -244,20 +1021,119 @@ msgstr "Tempo Total" msgid "Total test time for all commits/merges" msgstr "Tempo de teste total para todos os commits/merges" +msgid "Unstar" +msgstr "Desmarcar" + +msgid "Upload New File" +msgstr "Enviar Novo Arquivo" + +msgid "Upload file" +msgstr "Enviar arquivo" + +msgid "Use your global notification setting" +msgstr "Utilizar configuração de notificação global" + +msgid "VisibilityLevel|Internal" +msgstr "VisibilityLevel|Interno" + +msgid "VisibilityLevel|Private" +msgstr "VisibilityLevel|Privado" + +msgid "VisibilityLevel|Public" +msgstr "VisibilityLevel|Público" + msgid "Want to see the data? Please ask an administrator for access." msgstr "Precisa visualizar os dados? Solicite acesso ao administrador." msgid "We don't have enough data to show this stage." -msgstr "Não temos dados suficientes para mostrar esta fase." +msgstr "Esta etapa não possui dados suficientes para exibição." + +msgid "Withdraw Access Request" +msgstr "Remover Requisição de Acesso" + +msgid "" +"You are going to remove %{project_name_with_namespace}.\n" +"Removed project CANNOT be restored!\n" +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá remover %{project_name_with_namespace}.\n" +"O projeto removido NÃO PODE ser restaurado!\n" +"Tem certeza ABSOLUTA?" + +msgid "" +"You are going to remove the fork relationship to source project " +"%{forked_from_project}. Are you ABSOLUTELY sure?" +msgstr "" +"Você ira remover o relacionamento de fork com o projeto original " +"%{forked_from_project}. Tem certeza ABSOLUTA?" + +msgid "" +"You are going to transfer %{project_name_with_namespace} to another owner. " +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá transferir %{project_name_with_namespace} para outro proprietário. " +"Tem certeza ABSOLUTA?" + +msgid "You can only add files when you are on a branch" +msgstr "Você somente pode adicionar arquivos quando estiver em um branch" msgid "You have reached your project limit" -msgstr "" +msgstr "Você atingiu o limite de seu projeto" + +msgid "You must sign in to star a project" +msgstr "Você deve estar autenticado para marcar um projeto" msgid "You need permission." msgstr "Você precisa de permissão." +msgid "You will not get any notifications via email" +msgstr "Você não será notificado por email" + +msgid "You will only receive notifications for the events you choose" +msgstr "Você será notificado apenas sobre eventos selecionados" + +msgid "" +"You will only receive notifications for threads you have participated in" +msgstr "Você será notificado apenas sobre tópicos nos quais participou" + +msgid "You will receive notifications for any activity" +msgstr "Você será notificado sobre qualquer atividade" + +msgid "" +"You will receive notifications only for comments in which you were " +"@mentioned" +msgstr "Você será notificado apenas sobre comentários que te @mencionam" + +msgid "" +"You won't be able to pull or push project code via %{protocol} until you " +"%{set_password_link} on your account" +msgstr "" +"Você não poderá fazer pull ou push via %{protocol} até que " +"%{set_password_link} para sua conta" + +msgid "" +"You won't be able to pull or push project code via SSH until you " +"%{add_ssh_key_link} to your profile" +msgstr "" +"Você não conseguirá fazer pull ou push no projeto via SSH até que adicione " +"%{add_ssh_key_link} ao seu perfil" + +msgid "Your name" +msgstr "Seu nome" + msgid "day" msgid_plural "days" msgstr[0] "dia" msgstr[1] "dias" +msgid "new merge request" +msgstr "novo merge request" + +msgid "notification emails" +msgstr "emails de notificação" + +msgid "parent" +msgid_plural "parents" +msgstr[0] "pai" +msgstr[1] "pais" + From 4a38690b68f290713b2e39975d5a2c47c951c4ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 28 Jun 2017 18:58:21 +0800 Subject: [PATCH 07/61] Repair the wrong deletion of the author --- locale/pt_BR/gitlab.po | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 6377ed36e48..b3d5e95510d 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,4 +1,6 @@ +# Alexandre Alencar , 2017. #zanata # Fabio Beneditto , 2017. #zanata +# Leandro Nunes dos Santos , 2017. #zanata # Huang Tao , 2017. #zanata msgid "" msgstr "" From f3d49ed0398f2ab5775a01b955ec3297045425ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 11:41:45 +0800 Subject: [PATCH 08/61] supplement portuguese brazil translation Fix #33672 --- locale/pt_BR/gitlab.po | 1013 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 945 insertions(+), 68 deletions(-) diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index fe6d51c36ac..97cdafedb9a 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,28 +1,248 @@ # Alexandre Alencar , 2017. #zanata +# Bruno Guimarães , 2017. #zanata # Fabio Beneditto , 2017. #zanata -# Leandro Nunes dos Santos , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-05-04 19:24-0500\n" +"POT-Creation-Date: 2017-06-12 19:29-0500\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-05 03:29-0400\n" -"Last-Translator: Alexandre Alencar \n" -"Language-Team: Portuguese (Brazil)\n" +"PO-Revision-Date: 2017-06-13 04:05-0400\n" +"Last-Translator: Bruno Guimarães \n" +"Language-Team: Portuguese (Brazil) (https://translate.zanata.org/project/view/GitLab)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" +msgid "%{commit_author_link} committed %{commit_timeago}" +msgstr "%{commit_author_link} fez commit %{commit_timeago}" + +msgid "About auto deploy" +msgstr "Sobre a implantação automática" + +msgid "Active" +msgstr "Ativo" + +msgid "Activity" +msgstr "Atividade" + +msgid "Add Changelog" +msgstr "Adicionar registro de mudanças" + +msgid "Add Contribution guide" +msgstr "Adicionar Guia de contribuição" + +msgid "Add License" +msgstr "Adicionar Licença" + +msgid "Add an SSH key to your profile to pull or push via SSH." +msgstr "Adicionar chave SSH ao seu perfil para fazer pull ou push via SSH." + +msgid "Add new directory" +msgstr "Adicionar novo diretório" + +msgid "Archived project! Repository is read-only" +msgstr "Projeto arquivado! O repositório é somente leitura" + +msgid "Are you sure you want to delete this pipeline schedule?" +msgstr "Tem certeza que deseja excluir este agendamento de pipeline?" + +msgid "Attach a file by drag & drop or %{upload_link}" +msgstr "Para anexar arquivo, arraste e solte ou %{upload_link}" + +msgid "Branch" +msgid_plural "Branches" +msgstr[0] "Branch" +msgstr[1] "Branches" + +msgid "" +"Branch %{branch_name} was created. To set up auto deploy, " +"choose a GitLab CI Yaml template and commit your changes. " +"%{link_to_autodeploy_doc}" +msgstr "" +"O branch %{branch_name} foi criado. Para configurar a auto " +"implantação, selecione um modelo de Yaml do GitLab CI e registre suas " +"mudanças. \n" +"%{link_to_autodeploy_doc}" + +msgid "Branches" +msgstr "Branches" + +msgid "Browse files" +msgstr "Navegar pelos arquivos" + msgid "ByAuthor|by" -msgstr "por" +msgstr "ByAuthor|por" + +msgid "CI configuration" +msgstr "Configuração da Integração Contínua" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "ChangeTypeActionLabel|Pick into branch" +msgstr "ChangeTypeActionLabel|Pick para um branch" + +msgid "ChangeTypeActionLabel|Revert in branch" +msgstr "ChangeTypeActionLabel|Reverter no branch" + +msgid "ChangeTypeAction|Cherry-pick" +msgstr "ChangeTypeAction|Cherry-pick" + +msgid "ChangeType|commit" +msgstr "ChangeType|commit" + +msgid "ChangeType|merge request" +msgstr "ChangeType|merge request" + +msgid "Changelog" +msgstr "Registro de mudanças" + +msgid "Charts" +msgstr "Gráficos" + +msgid "Cherry-pick this commit" +msgstr "Cherry-pick esse commit" + +msgid "Cherry-pick this merge-request" +msgstr "Cherry-pick esse merge-request" + +msgid "CiStatusLabel|canceled" +msgstr "CiStatusLabel|cancelado" + +msgid "CiStatusLabel|created" +msgstr "CiStatusLabel|criado" + +msgid "CiStatusLabel|failed" +msgstr "CiStatusLabel|falhou" + +msgid "CiStatusLabel|manual action" +msgstr "CiStatusLabel|ação manual" + +msgid "CiStatusLabel|passed" +msgstr "CiStatusLabel|passou" + +msgid "CiStatusLabel|passed with warnings" +msgstr "CiStatusLabel|passou com avisos" + +msgid "CiStatusLabel|pending" +msgstr "CiStatusLabel|pendente" + +msgid "CiStatusLabel|skipped" +msgstr "CiStatusLabel|ignorado" + +msgid "CiStatusLabel|waiting for manual action" +msgstr "CiStatusLabel|aguardando ação manual" + +msgid "CiStatusText|blocked" +msgstr "CiStatusText|bloqueado" + +msgid "CiStatusText|canceled" +msgstr "CiStatusText|cancelado" + +msgid "CiStatusText|created" +msgstr "CiStatusText|criado" + +msgid "CiStatusText|failed" +msgstr "CiStatusText|falhou" + +msgid "CiStatusText|manual" +msgstr "CiStatusText|manual" + +msgid "CiStatusText|passed" +msgstr "CiStatusText|passou" + +msgid "CiStatusText|pending" +msgstr "CiStatusText|pendente" + +msgid "CiStatusText|skipped" +msgstr "CiStatusText|ignorado" + +msgid "CiStatus|running" +msgstr "CiStatus|executando" msgid "Commit" msgid_plural "Commits" -msgstr[0] "Commit" -msgstr[1] "Commits" +msgstr[0] "Conjunto de mudanças" +msgstr[1] "Conjuntos de mudanças" + +msgid "Commit message" +msgstr "Mensagem do conjunto de mudanças" + +msgid "CommitMessage|Add %{file_name}" +msgstr "CommitMessage|Adicionar %{file_name}" + +msgid "Commits" +msgstr "Conjuntos de mudanças" + +msgid "Commits|History" +msgstr "Commits|Histórico" + +msgid "Committed by" +msgstr "Entregue por" + +msgid "Compare" +msgstr "Comparar" + +msgid "Contribution guide" +msgstr "Guia de contribuição" + +msgid "Contributors" +msgstr "Contribuidores" + +msgid "Copy URL to clipboard" +msgstr "Copiar URL para área de transferência" + +msgid "Copy commit SHA to clipboard" +msgstr "Copiar SHA do conjunto de mudanças para a área de transferência" + +msgid "Create New Directory" +msgstr "Criar Novo Diretório" + +msgid "Create directory" +msgstr "Criar diretório" + +msgid "Create empty bare repository" +msgstr "Criar repositório centralizado vazio" + +msgid "Create merge request" +msgstr "Criar solicitação de incorporação" + +msgid "Create new..." +msgstr "Criar novo..." + +msgid "CreateNewFork|Fork" +msgstr "CreateNewFork|Fork" + +msgid "CreateTag|Tag" +msgstr "CreateTag|Tag" + +msgid "Cron Timezone" +msgstr "Fuso horário do cron" + +msgid "Cron syntax" +msgstr "Sintaxe do cron" + +msgid "Custom" +msgstr "Personalizar" + +msgid "Custom notification events" +msgstr "Eventos de notificação personalizados" + +msgid "" +"Custom notification levels are the same as participating levels. With custom " +"notification levels you will also receive notifications for select events. " +"To find out more, check out %{notification_link}." +msgstr "" +"Níveis de notificação personalizados são equivalentes a níveis de " +"participação. Com níveis de notificação personalizados você também será " +"notificado sobre eventos selecionados. Para mais informações, visite " +"%{notification_link}." + +msgid "Cycle Analytics" +msgstr "Análise de Ciclo" msgid "" "Cycle Analytics gives an overview of how much time it takes to go from idea " @@ -32,63 +252,222 @@ msgstr "" "para ir para produção em seu projeto." msgid "CycleAnalyticsStage|Code" -msgstr "Código" +msgstr "CycleAnalyticsStage|Código" msgid "CycleAnalyticsStage|Issue" -msgstr "Tarefa" +msgstr "CycleAnalyticsStage|Relato" msgid "CycleAnalyticsStage|Plan" -msgstr "Plano" +msgstr "CycleAnalyticsStage|Plano" msgid "CycleAnalyticsStage|Production" -msgstr "Produção" +msgstr "CycleAnalyticsStage|Produção" msgid "CycleAnalyticsStage|Review" -msgstr "Revisão" +msgstr "CycleAnalyticsStage|Revisão" msgid "CycleAnalyticsStage|Staging" -msgstr "Homologação" +msgstr "CycleAnalyticsStage|Homologação" msgid "CycleAnalyticsStage|Test" -msgstr "Teste" +msgstr "CycleAnalyticsStage|Teste" + +msgid "Define a custom pattern with cron syntax" +msgstr "Defina um padrão personalizado utilizando a sintaxe do cron" + +msgid "Delete" +msgstr "Excluir" msgid "Deploy" msgid_plural "Deploys" msgstr[0] "Implantação" msgstr[1] "Implantações" +msgid "Description" +msgstr "Descrição" + +msgid "Directory name" +msgstr "Nome do diretório" + +msgid "Don't show again" +msgstr "Não exibir novamente" + +msgid "Download" +msgstr "Baixar" + +msgid "Download tar" +msgstr "Baixar tar" + +msgid "Download tar.bz2" +msgstr "Baixar tar.bz2" + +msgid "Download tar.gz" +msgstr "Baixar tar.gz" + +msgid "Download zip" +msgstr "Baixar zip" + +msgid "DownloadArtifacts|Download" +msgstr "DownloadArtifacts|Baixar" + +msgid "DownloadCommit|Email Patches" +msgstr "DownloadCommit|Email com as mudanças" + +msgid "DownloadCommit|Plain Diff" +msgstr "DownloadCommit|Arquivo de texto com as mudanças" + +msgid "DownloadSource|Download" +msgstr "DownloadSource|Baixar" + +msgid "Edit" +msgstr "Alterar" + +msgid "Edit Pipeline Schedule %{id}" +msgstr "Alterar Agendamento do Pipeline %{id}" + +msgid "Every day (at 4:00am)" +msgstr "Todos os dias (às 4:00)" + +msgid "Every month (on the 1st at 4:00am)" +msgstr "Todos os meses (no dia primeiro às 4:00)" + +msgid "Every week (Sundays at 4:00am)" +msgstr "Toda semana (domingos às 4:00)" + +msgid "Failed to change the owner" +msgstr "Erro ao alterar o proprietário" + +msgid "Failed to remove the pipeline schedule" +msgstr "Erro ao excluir o agendamento do pipeline" + +msgid "Files" +msgstr "Arquivos" + +msgid "Find by path" +msgstr "Localizar por caminho" + +msgid "Find file" +msgstr "Localizar arquivo" + msgid "FirstPushedBy|First" -msgstr "Primeiro" +msgstr "FirstPushedBy|Primeiro" msgid "FirstPushedBy|pushed by" -msgstr "publicado por" +msgstr "FirstPushedBy|publicado por" + +msgid "Fork" +msgid_plural "Forks" +msgstr[0] "Bifurcação" +msgstr[1] "Bifurcações" + +msgid "ForkedFromProjectPath|Forked from" +msgstr "ForkedFromProjectPath|Forked de" msgid "From issue creation until deploy to production" -msgstr "Da criação de tarefas até a implantação para a produção" +msgstr "Da abertura de tarefas até a implantação para a produção" msgid "From merge request merge until deploy to production" -msgstr "Da incorporação do merge request até a implantação em produção" +msgstr "" +"Da aceitação da solicitação de incorporação até a implantação em produção" + +msgid "Go to your fork" +msgstr "Ir para sua bifurcação" + +msgid "GoToYourFork|Fork" +msgstr "GoToYourFork|Bifurcação" + +msgid "Home" +msgstr "Início" + +msgid "Housekeeping successfully started" +msgstr "Manutenção iniciada com sucesso" + +msgid "Import repository" +msgstr "Importar repositório" + +msgid "Interval Pattern" +msgstr "Padrão de intervalo" msgid "Introducing Cycle Analytics" msgstr "Apresentando a Análise de Ciclo" +msgid "LFSStatus|Disabled" +msgstr "LFSStatus|Desabilitado" + +msgid "LFSStatus|Enabled" +msgstr "LFSStatus|Habilitado" + msgid "Last %d day" msgid_plural "Last %d days" msgstr[0] "Último %d dia" msgstr[1] "Últimos %d dias" +msgid "Last Pipeline" +msgstr "Último Pipeline" + +msgid "Last Update" +msgstr "Última Atualização" + +msgid "Last commit" +msgstr "Último conjunto de mudanças" + +msgid "Learn more in the" +msgstr "Saiba mais em" + +msgid "Leave group" +msgstr "Sair do grupo" + +msgid "Leave project" +msgstr "Sair do projeto" + msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" -msgstr[0] "Limitado a mostrar %d evento no máximo" -msgstr[1] "Limitado a mostrar %d eventos no máximo" +msgstr[0] "Limitado a mostrar %d evento, no máximo" +msgstr[1] "Limitado a mostrar %d eventos, no máximo" msgid "Median" msgstr "Mediana" +msgid "MissingSSHKeyWarningLink|add an SSH key" +msgstr "MissingSSHKeyWarningLink|adicione uma chave SSH" + msgid "New Issue" msgid_plural "New Issues" -msgstr[0] "Nova Tarefa" -msgstr[1] "Novas Tarefas" +msgstr[0] "Novo Relato" +msgstr[1] "Novos Relatos" + +msgid "New Pipeline Schedule" +msgstr "Novo Agendamento de Pipeline" + +msgid "New branch" +msgstr "Nova ramificação" + +msgid "New directory" +msgstr "Novo diretório" + +msgid "New file" +msgstr "Novo arquivo" + +msgid "New issue" +msgstr "Novo relato" + +msgid "New merge request" +msgstr "Nova solicitação de incorporação" + +msgid "New schedule" +msgstr "Novo agendamento" + +msgid "New snippet" +msgstr "Novo snippet" + +msgid "New tag" +msgstr "Nova tag" + +msgid "No repository" +msgstr "Nenhum repositório" + +msgid "No schedules" +msgstr "Nenhum agendamento" msgid "Not available" msgstr "Não disponível" @@ -96,114 +475,376 @@ msgstr "Não disponível" msgid "Not enough data" msgstr "Dados insuficientes" +msgid "Notification events" +msgstr "Eventos de notificação" + +msgid "NotificationEvent|Close issue" +msgstr "NotificationEvent|Fechar relato" + +msgid "NotificationEvent|Close merge request" +msgstr "NotificationEvent|Fechar solicitação de incorporação" + +msgid "NotificationEvent|Failed pipeline" +msgstr "NotificationEvent|Falha no pipeline" + +msgid "NotificationEvent|Merge merge request" +msgstr "NotificationEvent|Aceitar merge request" + +msgid "NotificationEvent|New issue" +msgstr "NotificationEvent|Novo relato" + +msgid "NotificationEvent|New merge request" +msgstr "NotificationEvent|Novo merge request" + +msgid "NotificationEvent|New note" +msgstr "NotificationEvent|Novo comentário" + +msgid "NotificationEvent|Reassign issue" +msgstr "NotificationEvent|Reatribuir relato" + +msgid "NotificationEvent|Reassign merge request" +msgstr "NotificationEvent|Reatribuir merge request" + +msgid "NotificationEvent|Reopen issue" +msgstr "NotificationEvent|Reabrir relato" + +msgid "NotificationEvent|Successful pipeline" +msgstr "NotificationEvent|Pipeline bem sucedido" + +msgid "NotificationLevel|Custom" +msgstr "NotificationLevel|Personalizar" + +msgid "NotificationLevel|Disabled" +msgstr "NotificationLevel|Desabilitado" + +msgid "NotificationLevel|Global" +msgstr "NotificationLevel|Global" + +msgid "NotificationLevel|On mention" +msgstr "NotificationLevel|Quando mencionado" + +msgid "NotificationLevel|Participate" +msgstr "NotificationLevel|Participar" + +msgid "NotificationLevel|Watch" +msgstr "NotificationLevel|Observar" + +msgid "OfSearchInADropdown|Filter" +msgstr "OfSearchInADropdown|Filtrar" + msgid "OpenedNDaysAgo|Opened" -msgstr "Aberto" +msgstr "OpenedNDaysAgo|Aberto" + +msgid "Options" +msgstr "Opções" + +msgid "Owner" +msgstr "Proprietário" + +msgid "Pipeline" +msgstr "Pipeline" msgid "Pipeline Health" msgstr "Saúde da Pipeline" +msgid "Pipeline Schedule" +msgstr "Agendamento da Pipeline" + +msgid "Pipeline Schedules" +msgstr "Agendamentos da Pipeline" + +msgid "PipelineSchedules|Activated" +msgstr "PipelineSchedules|Ativado" + +msgid "PipelineSchedules|Active" +msgstr "PipelineSchedules|Ativo" + +msgid "PipelineSchedules|All" +msgstr "PipelineSchedules|Todos" + +msgid "PipelineSchedules|Inactive" +msgstr "PipelineSchedules|Inativo" + +msgid "PipelineSchedules|Next Run" +msgstr "PipelineSchedules|Próxima Execução" + +msgid "PipelineSchedules|None" +msgstr "PipelineSchedules|Nenhum" + +msgid "PipelineSchedules|Provide a short description for this pipeline" +msgstr "PipelineSchedules|Digite uma descrição curta para esta pipeline" + +msgid "PipelineSchedules|Take ownership" +msgstr "PipelineSchedules|Tornar-se proprietário" + +msgid "PipelineSchedules|Target" +msgstr "PipelineSchedules|Destino" + +msgid "Project '%{project_name}' queued for deletion." +msgstr "Projeto'%{project_name}' marcado para exclusão." + +msgid "Project '%{project_name}' was successfully created." +msgstr "Projeto '%{project_name}' criado com sucesso." + +msgid "Project '%{project_name}' was successfully updated." +msgstr "Projeto '%{project_name}' atualizado com sucesso." + +msgid "Project '%{project_name}' will be deleted." +msgstr "Projeto '%{project_name}' será excluído." + +msgid "Project access must be granted explicitly to each user." +msgstr "" +"Acesso ao projeto deve ser concedido explicitamente para cada usuário." + +msgid "Project export could not be deleted." +msgstr "A exportação do projeto não pôde ser excluída." + +msgid "Project export has been deleted." +msgstr "Exportação do projeto excluída." + +msgid "" +"Project export link has expired. Please generate a new export from your " +"project settings." +msgstr "" +"O link para a exportação do projeto expirou. Favor gerar uma nova exportação " +"a partir das configurações do projeto." + +msgid "Project export started. A download link will be sent by email." +msgstr "" +"Exportação do projeto iniciada. Um link para baixá-la será enviado por email." +"" + +msgid "Project home" +msgstr "Página inicial do projeto" + +msgid "ProjectFeature|Disabled" +msgstr "ProjectFeature|Desabilitado" + +msgid "ProjectFeature|Everyone with access" +msgstr "ProjectFeature|Todos que possuem acesso" + +msgid "ProjectFeature|Only team members" +msgstr "ProjectFeature|Apenas membros do time" + +msgid "ProjectFileTree|Name" +msgstr "ProjectFileTree|Nome" + +msgid "ProjectLastActivity|Never" +msgstr "ProjectLastActivity|Nunca" + msgid "ProjectLifecycle|Stage" -msgstr "Etapa" +msgstr "PipelineSchedules|Etapa" + +msgid "ProjectNetworkGraph|Graph" +msgstr "ProjectNetworkGraph|Árvore" msgid "Read more" -msgstr "Ler mais" +msgstr "Leia mais" + +msgid "Readme" +msgstr "Leia-me" + +msgid "RefSwitcher|Branches" +msgstr "RefSwitcher|Ramificações" + +msgid "RefSwitcher|Tags" +msgstr "RefSwitcher|Tags" msgid "Related Commits" -msgstr "Commits Relacionados" +msgstr "Conjuntos de Mudanças Relacionados" msgid "Related Deployed Jobs" -msgstr "Jobs Relacionados Incorporados" +msgstr "Tarefas Implantadas Relacionadas" msgid "Related Issues" -msgstr "Tarefas Relacionadas" +msgstr "Relatos Relacionados" msgid "Related Jobs" -msgstr "Jobs Relacionados" +msgstr "Tarefas Relacionadas" msgid "Related Merge Requests" -msgstr "Merge Requests Relacionados" +msgstr "Solicitações de Incorporação Relacionadas" msgid "Related Merged Requests" -msgstr "Merge Requests Relacionados" +msgstr "Solicitações de Incorporação Aceitas Relacionadas" + +msgid "Remind later" +msgstr "Lembrar mais tarde" + +msgid "Remove project" +msgstr "Remover projeto" + +msgid "Request Access" +msgstr "Solicitar acesso" + +msgid "Revert this commit" +msgstr "Reverter este conjunto de mudanças" + +msgid "Revert this merge-request" +msgstr "Reverter esta solicitação de incorporação" + +msgid "Save pipeline schedule" +msgstr "Salvar agendamento da pipeline" + +msgid "Schedule a new pipeline" +msgstr "Agendar nova pipeline" + +msgid "Scheduling Pipelines" +msgstr "Agendando pipelines" + +msgid "Search branches and tags" +msgstr "Procurar ramificações e tags" + +msgid "Select Archive Format" +msgstr "Selecionar Formato do Arquivo" + +msgid "Select a timezone" +msgstr "Selecionar fuso horário" + +msgid "Select target branch" +msgstr "Selecionar ramificação de destino" + +msgid "Set a password on your account to pull or push via %{protocol}" +msgstr "" +"Defina uma senha para sua conta para aceitar ou entregar código via " +"%{protocol}" + +msgid "Set up CI" +msgstr "Configurar CI" + +msgid "Set up Koding" +msgstr "Configurar Koding" + +msgid "Set up auto deploy" +msgstr "Configurar auto implantação" + +msgid "SetPasswordToCloneLink|set a password" +msgstr "SetPasswordToCloneLink|defina uma senha" msgid "Showing %d event" msgid_plural "Showing %d events" msgstr[0] "Mostrando %d evento" msgstr[1] "Mostrando %d eventos" +msgid "Source code" +msgstr "Código-fonte" + +msgid "StarProject|Star" +msgstr "StarProject|Marcar" + +msgid "Start a new merge request with these changes" +msgstr "" +"Criar uma nova solicitação de incorporação com estas " +"mudanças" + +msgid "Switch branch/tag" +msgstr "Trocar ramificação/tag" + +msgid "Tag" +msgid_plural "Tags" +msgstr[0] "Tag" +msgstr[1] "Tags" + +msgid "Tags" +msgstr "Tags" + +msgid "Target Branch" +msgstr "Ramificação de destino" + msgid "" "The coding stage shows the time from the first commit to creating the merge " "request. The data will automatically be added here once you create your " "first merge request." msgstr "" -"O estágio de codificação mostra o tempo desde o primeiro commit até a " -"criação do merge request. \n" -"Os dados serão automaticamente adicionados aqui uma vez que você tenha " -"criado seu primeiro merge request." +"A etapa de codificação mostra o tempo desde a entrega do primeiro conjunto " +"de mudanças até a criação da solicitação de incorporação. Os dados serão " +"automaticamente adicionados aqui desde o momento de criação da solicitação " +"de incorporação." msgid "The collection of events added to the data gathered for that stage." -msgstr "" -"A coleção de eventos adicionados aos dados coletados para esse estágio." +msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa." + +msgid "The fork relationship has been removed." +msgstr "O relacionamento como fork foi removido." msgid "" "The issue stage shows the time it takes from creating an issue to assigning " "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"O estágio em questão mostra o tempo que leva desde a criação de uma tarefa " -"até a sua assinatura para um milestone, ou a sua adição para a lista no seu " -"Painel de Tarefas. Comece a criar tarefas para ver dados para esta etapa." +"A etapa de relatos mostra o tempo que leva desde a criação de um relato até " +"sua atribuição a um marco, ou sua adição a uma lista no seu Quadro de " +"Relatos. Comece a criar relatos para ver dados para esta etapa." msgid "The phase of the development lifecycle." msgstr "A fase do ciclo de vida do desenvolvimento." +msgid "" +"The pipelines schedule runs pipelines in the future, repeatedly, for " +"specific branches or tags. Those scheduled pipelines will inherit limited " +"project access based on their associated user." +msgstr "" +"O agendamento de pipeline executa pipelines no futuro, repetidamente, para " +"ramificações ou tags específicas. Essas pipelines agendadas terão acesso " +"limitado ao projeto baseado no seu usuário associado." + msgid "" "The planning stage shows the time from the previous step to pushing your " "first commit. This time will be added automatically once you push your first " "commit." msgstr "" -"A fase de planejamento mostra o tempo do passo anterior até empurrar o seu " -"primeiro commit. Este tempo será adicionado automaticamente assim que você " -"realizar seu primeiro commit." +"A etapa de planejamento mostra o tempo do passo anterior até a publicação de " +"seu primeiro conjunto de mudanças. Este tempo será adicionado " +"automaticamente assim que você enviar seu primeiro conjunto de mudanças." msgid "" "The production stage shows the total time it takes between creating an issue " "and deploying the code to production. The data will be automatically added " "once you have completed the full idea to production cycle." msgstr "" -"O estágio de produção mostra o tempo total que leva entre criar uma tarefa e " -"implantar o código na produção. Os dados serão adicionados automaticamente " -"até que você complete todo o ciclo de produção." +"A etapa de produção mostra o tempo total que leva entre criar um relato e " +"implantar o código em produção. Os dados serão adicionados automaticamente " +"assim que você completar todo o ciclo de produção." + +msgid "The project can be accessed by any logged in user." +msgstr "O projeto pode ser acessado por qualquer usuário autenticado." + +msgid "The project can be accessed without any authentication." +msgstr "O projeto pode ser acessado sem a necessidade de autenticação." + +msgid "The repository for this project does not exist." +msgstr "O repositório para este projeto não existe." msgid "" "The review stage shows the time from creating the merge request to merging " "it. The data will automatically be added after you merge your first merge " "request." msgstr "" -"A etapa de revisão mostra o tempo de criação de um merge request até que o " -"merge seja feito. Os dados serão automaticamente adicionados depois que você " -"fizer seu primeiro merge request." +"A etapa de revisão mostra o tempo de criação de uma solicitação de " +"incorporação até sua aceitação. Os dados serão automaticamente adicionados " +"depois que sua primeira solicitação de incorporação for aceita." msgid "" "The staging stage shows the time between merging the MR and deploying code " "to the production environment. The data will be automatically added once you " "deploy to production for the first time." msgstr "" -"O estágio de estágio mostra o tempo entre a fusão do MR e o código de " -"implantação para o ambiente de produção. Os dados serão automaticamente " -"adicionados depois de implantar na produção pela primeira vez." +"A etapa de homologação mostra o tempo entre o aceite da solicitação de " +"incorporação e a implantação do código no ambiente de produção. Os dados " +"serão automaticamente adicionados depois que você implantar em produção pela " +"primeira vez." msgid "" "The testing stage shows the time GitLab CI takes to run every pipeline for " "the related merge request. The data will automatically be added after your " "first pipeline finishes running." msgstr "" -"A fase de teste mostra o tempo que o GitLab CI leva para executar cada " -"pipeline para o merge request relacionado. Os dados serão automaticamente " -"adicionados após a conclusão do primeiro pipeline." +"A etapa de testes mostra o tempo que o GitLab CI leva para executar cada " +"pipeline para a solicitação de incorporação associada. Os dados serão " +"automaticamente adicionados após a conclusão do primeiro pipeline." msgid "The time taken by each data entry gathered by that stage." -msgstr "O tempo necessário para cada entrada de dados reunida por essa etapa." +msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa." msgid "" "The value lying at the midpoint of a series of observed values. E.g., " @@ -211,32 +852,164 @@ msgid "" " 6." msgstr "" "O valor situado no ponto médio de uma série de valores observados. Ex., " -"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5 + 7) / 2 = 6." +"entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6." + +msgid "" +"This means you can not push code until you create an empty repository or " +"import existing one." +msgstr "" +"Isto significa que você não pode entregar código até que crie um repositório " +"vazio ou importe um existente." msgid "Time before an issue gets scheduled" -msgstr "Tempo até que uma tarefa seja planejada" +msgstr "Tempo até que um relato seja agendado" msgid "Time before an issue starts implementation" -msgstr "Tempo até que uma tarefa comece a ser implementada" +msgstr "Tempo até que um relato comece a ser implementado" msgid "Time between merge request creation and merge/close" -msgstr "Tempo entre a criação do merge request e o merge/fechamento" +msgstr "" +"Tempo entre a criação da solicitação de incorporação e a aceitação/" +"fechamento" msgid "Time until first merge request" -msgstr "Tempo até o primeiro merge request" +msgstr "Tempo até a primeira solicitação de incorporação" + +msgid "Timeago|%s days ago" +msgstr "Timeago|há %s dias" + +msgid "Timeago|%s days remaining" +msgstr "Timeago|%s dias restantes" + +msgid "Timeago|%s hours remaining" +msgstr "Timeago|%s horas restantes" + +msgid "Timeago|%s minutes ago" +msgstr "Timeago|há %s minutos" + +msgid "Timeago|%s minutes remaining" +msgstr "Timeago|%s minutos restantes" + +msgid "Timeago|%s months ago" +msgstr "Timeago|há %s meses" + +msgid "Timeago|%s months remaining" +msgstr "Timeago|%s meses restantes" + +msgid "Timeago|%s seconds remaining" +msgstr "Timeago|%s segundos restantes" + +msgid "Timeago|%s weeks ago" +msgstr "Timeago|há %s semanas" + +msgid "Timeago|%s weeks remaining" +msgstr "Timeago|%s semanas restantes" + +msgid "Timeago|%s years ago" +msgstr "Timeago|há %s anos" + +msgid "Timeago|%s years remaining" +msgstr "Timeago|%s anos restantes" + +msgid "Timeago|1 day remaining" +msgstr "Timeago|1 dia restante" + +msgid "Timeago|1 hour remaining" +msgstr "Timeago|1 hora restante" + +msgid "Timeago|1 minute remaining" +msgstr "Timeago|1 minuto restante" + +msgid "Timeago|1 month remaining" +msgstr "Timeago|1 mês restante" + +msgid "Timeago|1 week remaining" +msgstr "Timeago|1 semana restante" + +msgid "Timeago|1 year remaining" +msgstr "Timeago|1 ano restante" + +msgid "Timeago|Past due" +msgstr "Timeago|Venceu" + +msgid "Timeago|a day ago" +msgstr "Timeago|há um dia" + +msgid "Timeago|a month ago" +msgstr "Timeago|há um mês" + +msgid "Timeago|a week ago" +msgstr "Timeago|há uma semana" + +msgid "Timeago|a while" +msgstr "Timeago|há algum tempo" + +msgid "Timeago|a year ago" +msgstr "Timeago|há um ano" + +msgid "Timeago|about %s hours ago" +msgstr "Timeago|há cerca de %s horas" + +msgid "Timeago|about a minute ago" +msgstr "Timeago|há cerca de um minuto" + +msgid "Timeago|about an hour ago" +msgstr "Timeago|há cerca de uma hora" + +msgid "Timeago|in %s days" +msgstr "Timeago|em %s dias" + +msgid "Timeago|in %s hours" +msgstr "Timeago|em %s horas" + +msgid "Timeago|in %s minutes" +msgstr "Timeago|em %s minutos" + +msgid "Timeago|in %s months" +msgstr "Timeago|em %s meses" + +msgid "Timeago|in %s seconds" +msgstr "Timeago|em %s segundos" + +msgid "Timeago|in %s weeks" +msgstr "Timeago|em %s semanas" + +msgid "Timeago|in %s years" +msgstr "Timeago|em %s anos" + +msgid "Timeago|in 1 day" +msgstr "Timeago|em 1 dia" + +msgid "Timeago|in 1 hour" +msgstr "Timeago|em 1 hora" + +msgid "Timeago|in 1 minute" +msgstr "Timeago|em 1 minuto" + +msgid "Timeago|in 1 month" +msgstr "Timeago|em 1 mês" + +msgid "Timeago|in 1 week" +msgstr "Timeago|em 1 semana" + +msgid "Timeago|in 1 year" +msgstr "Timeago|em 1 ano" + +msgid "Timeago|less than a minute ago" +msgstr "Timeago|há menos de um minuto" msgid "Time|hr" msgid_plural "Time|hrs" -msgstr[0] "h" -msgstr[1] "hs" +msgstr[0] "Time|h" +msgstr[1] "Time|hs" msgid "Time|min" msgid_plural "Time|mins" -msgstr[0] "min" -msgstr[1] "mins" +msgstr[0] "Time|min" +msgstr[1] "Time|mins" msgid "Time|s" -msgstr "s" +msgstr "Time|s" msgid "Total Time" msgstr "Tempo Total" @@ -244,11 +1017,64 @@ msgstr "Tempo Total" msgid "Total test time for all commits/merges" msgstr "Tempo de teste total para todos os commits/merges" +msgid "Unstar" +msgstr "Desmarcar" + +msgid "Upload New File" +msgstr "Enviar Novo Arquivo" + +msgid "Upload file" +msgstr "Enviar arquivo" + +msgid "Use your global notification setting" +msgstr "Utilizar configuração de notificação global" + +msgid "VisibilityLevel|Internal" +msgstr "VisibilityLevel|Interno" + +msgid "VisibilityLevel|Private" +msgstr "VisibilityLevel|Privado" + +msgid "VisibilityLevel|Public" +msgstr "VisibilityLevel|Público" + msgid "Want to see the data? Please ask an administrator for access." msgstr "Precisa visualizar os dados? Solicite acesso ao administrador." msgid "We don't have enough data to show this stage." -msgstr "Não temos dados suficientes para mostrar esta fase." +msgstr "Esta etapa não possui dados suficientes para exibição." + +msgid "Withdraw Access Request" +msgstr "Remover Requisição de Acesso" + +msgid "" +"You are going to remove %{project_name_with_namespace}.\n" +"Removed project CANNOT be restored!\n" +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá remover %{project_name_with_namespace}.\n" +"O projeto removido NÃO PODE ser restaurado!\n" +"Tem certeza ABSOLUTA?" + +msgid "" +"You are going to remove the fork relationship to source project " +"%{forked_from_project}. Are you ABSOLUTELY sure?" +msgstr "" +"Você ira remover o relacionamento de fork com o projeto original " +"%{forked_from_project}. Tem certeza ABSOLUTA?" + +msgid "" +"You are going to transfer %{project_name_with_namespace} to another owner. " +"Are you ABSOLUTELY sure?" +msgstr "" +"Você irá transferir %{project_name_with_namespace} para outro proprietário. " +"Tem certeza ABSOLUTA?" + +msgid "You can only add files when you are on a branch" +msgstr "Você somente pode adicionar arquivos quando estiver em um branch" + +msgid "You must sign in to star a project" +msgstr "Você deve estar autenticado para marcar um projeto" msgid "You have reached your project limit" msgstr "" @@ -256,8 +1082,59 @@ msgstr "" msgid "You need permission." msgstr "Você precisa de permissão." +msgid "You will not get any notifications via email" +msgstr "Você não será notificado por email" + +msgid "You will only receive notifications for the events you choose" +msgstr "Você será notificado apenas sobre eventos selecionados" + +msgid "" +"You will only receive notifications for threads you have participated in" +msgstr "Você será notificado apenas sobre tópicos nos quais participou" + +msgid "You will receive notifications for any activity" +msgstr "Você será notificado sobre qualquer atividade" + +msgid "" +"You will receive notifications only for comments in which you were " +"@mentioned" +msgstr "Você será notificado apenas sobre comentários que te @mencionam" + +msgid "" +"You won't be able to pull or push project code via %{protocol} until you " +"%{set_password_link} on your account" +msgstr "" +"Você não poderá fazer pull ou push via %{protocol} até que " +"%{set_password_link} para sua conta" + +msgid "" +"You won't be able to pull or push project code via SSH until you " +"%{add_ssh_key_link} to your profile" +msgstr "" +"Você não conseguirá fazer pull ou push no projeto via SSH até que adicione " +"%{add_ssh_key_link} ao seu perfil" + +msgid "Your name" +msgstr "Seu nome" + msgid "day" msgid_plural "days" msgstr[0] "dia" msgstr[1] "dias" +msgid "notification emails" +msgstr "emails de notificação" + +msgid "parent" +msgid_plural "parents" +msgstr[0] "pai" +msgstr[1] "pais" + +msgid "pipeline schedules documentation" +msgstr "documentação do agendamento de pipelines" + +msgid "with stage" +msgid_plural "with stages" +msgstr[0] "com a etapa" +msgstr[1] "com as etapas" + From 2de12680d20e5818b94afb220d630281576b36ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 13:06:17 +0800 Subject: [PATCH 09/61] add changelog of supplement portuguese brazil translation --- ...33672-supplement_portuguese_brazil_translation_of_i18n.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml new file mode 100644 index 00000000000..605c360115e --- /dev/null +++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml @@ -0,0 +1,4 @@ +--- +title: Supplement Portuguese Brazil translation of Project Page & Repository Page +merge_request: 11958 +author: Huang Tao From 419c9b63ce05e9a6816b38e54bf89e1ee908cf52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 13:08:51 +0800 Subject: [PATCH 10/61] revise changelog --- .../33672-supplement_portuguese_brazil_translation_of_i18n.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml index 605c360115e..d2bdc631d2a 100644 --- a/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml +++ b/changelogs/unreleased/33672-supplement_portuguese_brazil_translation_of_i18n.yml @@ -1,4 +1,4 @@ --- title: Supplement Portuguese Brazil translation of Project Page & Repository Page -merge_request: 11958 +merge_request: 12156 author: Huang Tao From 85fcd7a18e7956baaa243442f5515a34c9a23ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 14 Jun 2017 11:41:45 +0800 Subject: [PATCH 11/61] supplement portuguese brazil translation Fix #33672 --- locale/pt_BR/gitlab.po | 167 ++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 84 deletions(-) diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 97cdafedb9a..6377ed36e48 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,17 +1,16 @@ -# Alexandre Alencar , 2017. #zanata -# Bruno Guimarães , 2017. #zanata # Fabio Beneditto , 2017. #zanata +# Huang Tao , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-12 19:29-0500\n" +"POT-Creation-Date: 2017-06-15 21:59-0500\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-13 04:05-0400\n" -"Last-Translator: Bruno Guimarães \n" -"Language-Team: Portuguese (Brazil) (https://translate.zanata.org/project/view/GitLab)\n" +"PO-Revision-Date: 2017-06-25 09:38-0400\n" +"Last-Translator: Copied by Zanata \n" +"Language-Team: Portuguese (Brazil)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" @@ -62,10 +61,9 @@ msgid "" "choose a GitLab CI Yaml template and commit your changes. " "%{link_to_autodeploy_doc}" msgstr "" -"O branch %{branch_name} foi criado. Para configurar a auto " -"implantação, selecione um modelo de Yaml do GitLab CI e registre suas " -"mudanças. \n" -"%{link_to_autodeploy_doc}" +"O branch %{branch_name} foi criado. Para configurar a " +"implantação automática, selecione um modelo de Yaml do GitLab CI e registre " +"suas mudanças. %{link_to_autodeploy_doc}" msgid "Branches" msgstr "Branches" @@ -91,11 +89,8 @@ msgstr "ChangeTypeActionLabel|Reverter no branch" msgid "ChangeTypeAction|Cherry-pick" msgstr "ChangeTypeAction|Cherry-pick" -msgid "ChangeType|commit" -msgstr "ChangeType|commit" - -msgid "ChangeType|merge request" -msgstr "ChangeType|merge request" +msgid "ChangeTypeAction|Revert" +msgstr "ChangeTypeAction|Reverter" msgid "Changelog" msgstr "Registro de mudanças" @@ -106,8 +101,8 @@ msgstr "Gráficos" msgid "Cherry-pick this commit" msgstr "Cherry-pick esse commit" -msgid "Cherry-pick this merge-request" -msgstr "Cherry-pick esse merge-request" +msgid "Cherry-pick this merge request" +msgstr "Cherry-pick esse merge request" msgid "CiStatusLabel|canceled" msgstr "CiStatusLabel|cancelado" @@ -165,23 +160,26 @@ msgstr "CiStatus|executando" msgid "Commit" msgid_plural "Commits" -msgstr[0] "Conjunto de mudanças" -msgstr[1] "Conjuntos de mudanças" +msgstr[0] "Commit" +msgstr[1] "Commits" msgid "Commit message" -msgstr "Mensagem do conjunto de mudanças" +msgstr "Mensagem de commit" + +msgid "CommitBoxTitle|Commit" +msgstr "CommitBoxTitle|Commit" msgid "CommitMessage|Add %{file_name}" msgstr "CommitMessage|Adicionar %{file_name}" msgid "Commits" -msgstr "Conjuntos de mudanças" +msgstr "Commits" msgid "Commits|History" msgstr "Commits|Histórico" msgid "Committed by" -msgstr "Entregue por" +msgstr "Commit feito por" msgid "Compare" msgstr "Comparar" @@ -196,7 +194,7 @@ msgid "Copy URL to clipboard" msgstr "Copiar URL para área de transferência" msgid "Copy commit SHA to clipboard" -msgstr "Copiar SHA do conjunto de mudanças para a área de transferência" +msgstr "Copiar SHA do commit para a área de transferência" msgid "Create New Directory" msgstr "Criar Novo Diretório" @@ -205,10 +203,10 @@ msgid "Create directory" msgstr "Criar diretório" msgid "Create empty bare repository" -msgstr "Criar repositório centralizado vazio" +msgstr "Criar repositório bruto vazio" msgid "Create merge request" -msgstr "Criar solicitação de incorporação" +msgstr "Criar merge request" msgid "Create new..." msgstr "Criar novo..." @@ -225,9 +223,6 @@ msgstr "Fuso horário do cron" msgid "Cron syntax" msgstr "Sintaxe do cron" -msgid "Custom" -msgstr "Personalizar" - msgid "Custom notification events" msgstr "Eventos de notificação personalizados" @@ -255,7 +250,7 @@ msgid "CycleAnalyticsStage|Code" msgstr "CycleAnalyticsStage|Código" msgid "CycleAnalyticsStage|Issue" -msgstr "CycleAnalyticsStage|Relato" +msgstr "CycleAnalyticsStage|Issue" msgid "CycleAnalyticsStage|Plan" msgstr "CycleAnalyticsStage|Plano" @@ -357,8 +352,8 @@ msgstr "FirstPushedBy|publicado por" msgid "Fork" msgid_plural "Forks" -msgstr[0] "Bifurcação" -msgstr[1] "Bifurcações" +msgstr[0] "Fork" +msgstr[1] "Forks" msgid "ForkedFromProjectPath|Forked from" msgstr "ForkedFromProjectPath|Forked de" @@ -371,10 +366,10 @@ msgstr "" "Da aceitação da solicitação de incorporação até a implantação em produção" msgid "Go to your fork" -msgstr "Ir para sua bifurcação" +msgstr "Ir para seu fork" msgid "GoToYourFork|Fork" -msgstr "GoToYourFork|Bifurcação" +msgstr "GoToYourFork|Fork" msgid "Home" msgstr "Início" @@ -409,11 +404,14 @@ msgid "Last Update" msgstr "Última Atualização" msgid "Last commit" -msgstr "Último conjunto de mudanças" +msgstr "Último commit" msgid "Learn more in the" msgstr "Saiba mais em" +msgid "Learn more in the|pipeline schedules documentation" +msgstr "Learn more in the|documentação de agendamento de pipeline" + msgid "Leave group" msgstr "Sair do grupo" @@ -433,14 +431,14 @@ msgstr "MissingSSHKeyWarningLink|adicione uma chave SSH" msgid "New Issue" msgid_plural "New Issues" -msgstr[0] "Novo Relato" -msgstr[1] "Novos Relatos" +msgstr[0] "Nova Issue" +msgstr[1] "Novas Issues" msgid "New Pipeline Schedule" msgstr "Novo Agendamento de Pipeline" msgid "New branch" -msgstr "Nova ramificação" +msgstr "Novo branch" msgid "New directory" msgstr "Novo diretório" @@ -449,10 +447,10 @@ msgid "New file" msgstr "Novo arquivo" msgid "New issue" -msgstr "Novo relato" +msgstr "Nova issue" msgid "New merge request" -msgstr "Nova solicitação de incorporação" +msgstr "Novo merge request" msgid "New schedule" msgstr "Novo agendamento" @@ -479,10 +477,10 @@ msgid "Notification events" msgstr "Eventos de notificação" msgid "NotificationEvent|Close issue" -msgstr "NotificationEvent|Fechar relato" +msgstr "NotificationEvent|Fechar issue" msgid "NotificationEvent|Close merge request" -msgstr "NotificationEvent|Fechar solicitação de incorporação" +msgstr "NotificationEvent|Fechar merge request" msgid "NotificationEvent|Failed pipeline" msgstr "NotificationEvent|Falha no pipeline" @@ -491,7 +489,7 @@ msgid "NotificationEvent|Merge merge request" msgstr "NotificationEvent|Aceitar merge request" msgid "NotificationEvent|New issue" -msgstr "NotificationEvent|Novo relato" +msgstr "NotificationEvent|Nova issue" msgid "NotificationEvent|New merge request" msgstr "NotificationEvent|Novo merge request" @@ -500,13 +498,13 @@ msgid "NotificationEvent|New note" msgstr "NotificationEvent|Novo comentário" msgid "NotificationEvent|Reassign issue" -msgstr "NotificationEvent|Reatribuir relato" +msgstr "NotificationEvent|Reatribuir issue" msgid "NotificationEvent|Reassign merge request" msgstr "NotificationEvent|Reatribuir merge request" msgid "NotificationEvent|Reopen issue" -msgstr "NotificationEvent|Reabrir relato" +msgstr "NotificationEvent|Reabrir issue" msgid "NotificationEvent|Successful pipeline" msgstr "NotificationEvent|Pipeline bem sucedido" @@ -580,6 +578,15 @@ msgstr "PipelineSchedules|Tornar-se proprietário" msgid "PipelineSchedules|Target" msgstr "PipelineSchedules|Destino" +msgid "PipelineSheduleIntervalPattern|Custom" +msgstr "PipelineSheduleIntervalPattern|Personalizado" + +msgid "Pipeline|with stage" +msgstr "Pipeline|com etapa" + +msgid "Pipeline|with stages" +msgstr "Pipeline|com etapas" + msgid "Project '%{project_name}' queued for deletion." msgstr "Projeto'%{project_name}' marcado para exclusão." @@ -645,28 +652,28 @@ msgid "Readme" msgstr "Leia-me" msgid "RefSwitcher|Branches" -msgstr "RefSwitcher|Ramificações" +msgstr "RefSwitcher|Branches" msgid "RefSwitcher|Tags" msgstr "RefSwitcher|Tags" msgid "Related Commits" -msgstr "Conjuntos de Mudanças Relacionados" +msgstr "Commits Relacionados" msgid "Related Deployed Jobs" msgstr "Tarefas Implantadas Relacionadas" msgid "Related Issues" -msgstr "Relatos Relacionados" +msgstr "Issues Relacionadas" msgid "Related Jobs" msgstr "Tarefas Relacionadas" msgid "Related Merge Requests" -msgstr "Solicitações de Incorporação Relacionadas" +msgstr "Merge Requests Relacionados" msgid "Related Merged Requests" -msgstr "Solicitações de Incorporação Aceitas Relacionadas" +msgstr "Merge Requests Relacionados" msgid "Remind later" msgstr "Lembrar mais tarde" @@ -678,10 +685,10 @@ msgid "Request Access" msgstr "Solicitar acesso" msgid "Revert this commit" -msgstr "Reverter este conjunto de mudanças" +msgstr "Reverter este commit" -msgid "Revert this merge-request" -msgstr "Reverter esta solicitação de incorporação" +msgid "Revert this merge request" +msgstr "Reverter esse merge request" msgid "Save pipeline schedule" msgstr "Salvar agendamento da pipeline" @@ -693,7 +700,7 @@ msgid "Scheduling Pipelines" msgstr "Agendando pipelines" msgid "Search branches and tags" -msgstr "Procurar ramificações e tags" +msgstr "Procurar branch e tags" msgid "Select Archive Format" msgstr "Selecionar Formato do Arquivo" @@ -702,7 +709,7 @@ msgid "Select a timezone" msgstr "Selecionar fuso horário" msgid "Select target branch" -msgstr "Selecionar ramificação de destino" +msgstr "Selecionar branch de destino" msgid "Set a password on your account to pull or push via %{protocol}" msgstr "" @@ -716,7 +723,7 @@ msgid "Set up Koding" msgstr "Configurar Koding" msgid "Set up auto deploy" -msgstr "Configurar auto implantação" +msgstr "Configurar implantação automática" msgid "SetPasswordToCloneLink|set a password" msgstr "SetPasswordToCloneLink|defina uma senha" @@ -732,13 +739,11 @@ msgstr "Código-fonte" msgid "StarProject|Star" msgstr "StarProject|Marcar" -msgid "Start a new merge request with these changes" -msgstr "" -"Criar uma nova solicitação de incorporação com estas " -"mudanças" +msgid "Start a %{new_merge_request} with these changes" +msgstr "Iniciar um %{new_merge_request} a partir dessas alterações" msgid "Switch branch/tag" -msgstr "Trocar ramificação/tag" +msgstr "Trocar branch/tag" msgid "Tag" msgid_plural "Tags" @@ -749,17 +754,16 @@ msgid "Tags" msgstr "Tags" msgid "Target Branch" -msgstr "Ramificação de destino" +msgstr "Branch de destino" msgid "" "The coding stage shows the time from the first commit to creating the merge " "request. The data will automatically be added here once you create your " "first merge request." msgstr "" -"A etapa de codificação mostra o tempo desde a entrega do primeiro conjunto " -"de mudanças até a criação da solicitação de incorporação. Os dados serão " -"automaticamente adicionados aqui desde o momento de criação da solicitação " -"de incorporação." +"A etapa de codificação mostra o tempo desde a entrega do primeiro commit até " +"a criação do merge request. Os dados serão automaticamente adicionados aqui " +"desde o momento de criação do merge request." msgid "The collection of events added to the data gathered for that stage." msgstr "A coleção de eventos adicionados aos dados coletados para essa etapa." @@ -772,9 +776,9 @@ msgid "" "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"A etapa de relatos mostra o tempo que leva desde a criação de um relato até " -"sua atribuição a um marco, ou sua adição a uma lista no seu Quadro de " -"Relatos. Comece a criar relatos para ver dados para esta etapa." +"A etapa de relatos mostra o tempo que leva desde a criação de uma issue até " +"sua atribuição a um marco, ou sua adição a uma lista no seu Issue Board. " +"Comece a criar issues para ver dados para esta etapa." msgid "The phase of the development lifecycle." msgstr "A fase do ciclo de vida do desenvolvimento." @@ -785,7 +789,7 @@ msgid "" "project access based on their associated user." msgstr "" "O agendamento de pipeline executa pipelines no futuro, repetidamente, para " -"ramificações ou tags específicas. Essas pipelines agendadas terão acesso " +"branches ou tags específicas. Essas pipelines agendadas terão acesso " "limitado ao projeto baseado no seu usuário associado." msgid "" @@ -802,7 +806,7 @@ msgid "" "and deploying the code to production. The data will be automatically added " "once you have completed the full idea to production cycle." msgstr "" -"A etapa de produção mostra o tempo total que leva entre criar um relato e " +"A etapa de produção mostra o tempo total que leva entre criar uma issue e " "implantar o código em produção. Os dados serão adicionados automaticamente " "assim que você completar todo o ciclo de produção." @@ -813,7 +817,7 @@ msgid "The project can be accessed without any authentication." msgstr "O projeto pode ser acessado sem a necessidade de autenticação." msgid "The repository for this project does not exist." -msgstr "O repositório para este projeto não existe." +msgstr "Não existe repositório para este projeto." msgid "" "The review stage shows the time from creating the merge request to merging " @@ -862,10 +866,10 @@ msgstr "" "vazio ou importe um existente." msgid "Time before an issue gets scheduled" -msgstr "Tempo até que um relato seja agendado" +msgstr "Tempo até que uma issue seja agendada" msgid "Time before an issue starts implementation" -msgstr "Tempo até que um relato comece a ser implementado" +msgstr "Tempo até que uma issue comece a ser implementado" msgid "Time between merge request creation and merge/close" msgstr "" @@ -1073,12 +1077,12 @@ msgstr "" msgid "You can only add files when you are on a branch" msgstr "Você somente pode adicionar arquivos quando estiver em um branch" +msgid "You have reached your project limit" +msgstr "Você atingiu o limite de seu projeto" + msgid "You must sign in to star a project" msgstr "Você deve estar autenticado para marcar um projeto" -msgid "You have reached your project limit" -msgstr "" - msgid "You need permission." msgstr "Você precisa de permissão." @@ -1122,6 +1126,9 @@ msgid_plural "days" msgstr[0] "dia" msgstr[1] "dias" +msgid "new merge request" +msgstr "novo merge request" + msgid "notification emails" msgstr "emails de notificação" @@ -1130,11 +1137,3 @@ msgid_plural "parents" msgstr[0] "pai" msgstr[1] "pais" -msgid "pipeline schedules documentation" -msgstr "documentação do agendamento de pipelines" - -msgid "with stage" -msgid_plural "with stages" -msgstr[0] "com a etapa" -msgstr[1] "com as etapas" - From 99f3e619a0cb6216f70cb98a267249dba4e45be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 28 Jun 2017 18:58:21 +0800 Subject: [PATCH 12/61] Repair the wrong deletion of the author --- locale/pt_BR/gitlab.po | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 6377ed36e48..b3d5e95510d 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -1,4 +1,6 @@ +# Alexandre Alencar , 2017. #zanata # Fabio Beneditto , 2017. #zanata +# Leandro Nunes dos Santos , 2017. #zanata # Huang Tao , 2017. #zanata msgid "" msgstr "" From c5539e08a9bb71faa8c9295b890f1e7a0b7f7ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 5 Jul 2017 15:13:29 +0800 Subject: [PATCH 13/61] remove repeat the context of msgstr --- locale/pt_BR/gitlab.po | 280 ++++++++++++++++++++--------------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index b3d5e95510d..1ea39894bb8 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -10,8 +10,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-25 09:38-0400\n" -"Last-Translator: Copied by Zanata \n" +"PO-Revision-Date: 2017-07-05 02:56-0400\n" +"Last-Translator: Huang Tao \n" "Language-Team: Portuguese (Brazil)\n" "Language: pt-BR\n" "X-Generator: Zanata 3.9.6\n" @@ -74,7 +74,7 @@ msgid "Browse files" msgstr "Navegar pelos arquivos" msgid "ByAuthor|by" -msgstr "ByAuthor|por" +msgstr "por" msgid "CI configuration" msgstr "Configuração da Integração Contínua" @@ -83,16 +83,16 @@ msgid "Cancel" msgstr "Cancelar" msgid "ChangeTypeActionLabel|Pick into branch" -msgstr "ChangeTypeActionLabel|Pick para um branch" +msgstr "Pick para um branch" msgid "ChangeTypeActionLabel|Revert in branch" -msgstr "ChangeTypeActionLabel|Reverter no branch" +msgstr "Reverter no branch" msgid "ChangeTypeAction|Cherry-pick" -msgstr "ChangeTypeAction|Cherry-pick" +msgstr "Cherry-pick" msgid "ChangeTypeAction|Revert" -msgstr "ChangeTypeAction|Reverter" +msgstr "Reverter" msgid "Changelog" msgstr "Registro de mudanças" @@ -107,58 +107,58 @@ msgid "Cherry-pick this merge request" msgstr "Cherry-pick esse merge request" msgid "CiStatusLabel|canceled" -msgstr "CiStatusLabel|cancelado" +msgstr "cancelado" msgid "CiStatusLabel|created" -msgstr "CiStatusLabel|criado" +msgstr "criado" msgid "CiStatusLabel|failed" -msgstr "CiStatusLabel|falhou" +msgstr "falhou" msgid "CiStatusLabel|manual action" -msgstr "CiStatusLabel|ação manual" +msgstr "ação manual" msgid "CiStatusLabel|passed" -msgstr "CiStatusLabel|passou" +msgstr "passou" msgid "CiStatusLabel|passed with warnings" -msgstr "CiStatusLabel|passou com avisos" +msgstr "passou com avisos" msgid "CiStatusLabel|pending" -msgstr "CiStatusLabel|pendente" +msgstr "pendente" msgid "CiStatusLabel|skipped" -msgstr "CiStatusLabel|ignorado" +msgstr "ignorado" msgid "CiStatusLabel|waiting for manual action" -msgstr "CiStatusLabel|aguardando ação manual" +msgstr "aguardando ação manual" msgid "CiStatusText|blocked" -msgstr "CiStatusText|bloqueado" +msgstr "bloqueado" msgid "CiStatusText|canceled" -msgstr "CiStatusText|cancelado" +msgstr "cancelado" msgid "CiStatusText|created" -msgstr "CiStatusText|criado" +msgstr "criado" msgid "CiStatusText|failed" -msgstr "CiStatusText|falhou" +msgstr "falhou" msgid "CiStatusText|manual" -msgstr "CiStatusText|manual" +msgstr "manual" msgid "CiStatusText|passed" -msgstr "CiStatusText|passou" +msgstr "passou" msgid "CiStatusText|pending" -msgstr "CiStatusText|pendente" +msgstr "pendente" msgid "CiStatusText|skipped" -msgstr "CiStatusText|ignorado" +msgstr "ignorado" msgid "CiStatus|running" -msgstr "CiStatus|executando" +msgstr "executando" msgid "Commit" msgid_plural "Commits" @@ -169,16 +169,16 @@ msgid "Commit message" msgstr "Mensagem de commit" msgid "CommitBoxTitle|Commit" -msgstr "CommitBoxTitle|Commit" +msgstr "Commit" msgid "CommitMessage|Add %{file_name}" -msgstr "CommitMessage|Adicionar %{file_name}" +msgstr "Adicionar %{file_name}" msgid "Commits" msgstr "Commits" msgid "Commits|History" -msgstr "Commits|Histórico" +msgstr "Histórico" msgid "Committed by" msgstr "Commit feito por" @@ -214,10 +214,10 @@ msgid "Create new..." msgstr "Criar novo..." msgid "CreateNewFork|Fork" -msgstr "CreateNewFork|Fork" +msgstr "Fork" msgid "CreateTag|Tag" -msgstr "CreateTag|Tag" +msgstr "Tag" msgid "Cron Timezone" msgstr "Fuso horário do cron" @@ -249,25 +249,25 @@ msgstr "" "para ir para produção em seu projeto." msgid "CycleAnalyticsStage|Code" -msgstr "CycleAnalyticsStage|Código" +msgstr "Código" msgid "CycleAnalyticsStage|Issue" -msgstr "CycleAnalyticsStage|Issue" +msgstr "Issue" msgid "CycleAnalyticsStage|Plan" -msgstr "CycleAnalyticsStage|Plano" +msgstr "Plano" msgid "CycleAnalyticsStage|Production" -msgstr "CycleAnalyticsStage|Produção" +msgstr "Produção" msgid "CycleAnalyticsStage|Review" -msgstr "CycleAnalyticsStage|Revisão" +msgstr "Revisão" msgid "CycleAnalyticsStage|Staging" -msgstr "CycleAnalyticsStage|Homologação" +msgstr "Homologação" msgid "CycleAnalyticsStage|Test" -msgstr "CycleAnalyticsStage|Teste" +msgstr "Teste" msgid "Define a custom pattern with cron syntax" msgstr "Defina um padrão personalizado utilizando a sintaxe do cron" @@ -305,16 +305,16 @@ msgid "Download zip" msgstr "Baixar zip" msgid "DownloadArtifacts|Download" -msgstr "DownloadArtifacts|Baixar" +msgstr "Baixar" msgid "DownloadCommit|Email Patches" -msgstr "DownloadCommit|Email com as mudanças" +msgstr "Email com as mudanças" msgid "DownloadCommit|Plain Diff" -msgstr "DownloadCommit|Arquivo de texto com as mudanças" +msgstr "Arquivo de texto com as mudanças" msgid "DownloadSource|Download" -msgstr "DownloadSource|Baixar" +msgstr "Baixar" msgid "Edit" msgstr "Alterar" @@ -347,10 +347,10 @@ msgid "Find file" msgstr "Localizar arquivo" msgid "FirstPushedBy|First" -msgstr "FirstPushedBy|Primeiro" +msgstr "Primeiro" msgid "FirstPushedBy|pushed by" -msgstr "FirstPushedBy|publicado por" +msgstr "publicado por" msgid "Fork" msgid_plural "Forks" @@ -358,7 +358,7 @@ msgstr[0] "Fork" msgstr[1] "Forks" msgid "ForkedFromProjectPath|Forked from" -msgstr "ForkedFromProjectPath|Forked de" +msgstr "Forked de" msgid "From issue creation until deploy to production" msgstr "Da abertura de tarefas até a implantação para a produção" @@ -371,7 +371,7 @@ msgid "Go to your fork" msgstr "Ir para seu fork" msgid "GoToYourFork|Fork" -msgstr "GoToYourFork|Fork" +msgstr "Fork" msgid "Home" msgstr "Início" @@ -389,10 +389,10 @@ msgid "Introducing Cycle Analytics" msgstr "Apresentando a Análise de Ciclo" msgid "LFSStatus|Disabled" -msgstr "LFSStatus|Desabilitado" +msgstr "Desabilitado" msgid "LFSStatus|Enabled" -msgstr "LFSStatus|Habilitado" +msgstr "Habilitado" msgid "Last %d day" msgid_plural "Last %d days" @@ -412,7 +412,7 @@ msgid "Learn more in the" msgstr "Saiba mais em" msgid "Learn more in the|pipeline schedules documentation" -msgstr "Learn more in the|documentação de agendamento de pipeline" +msgstr "documentação de agendamento de pipeline" msgid "Leave group" msgstr "Sair do grupo" @@ -429,7 +429,7 @@ msgid "Median" msgstr "Mediana" msgid "MissingSSHKeyWarningLink|add an SSH key" -msgstr "MissingSSHKeyWarningLink|adicione uma chave SSH" +msgstr "adicione uma chave SSH" msgid "New Issue" msgid_plural "New Issues" @@ -479,61 +479,61 @@ msgid "Notification events" msgstr "Eventos de notificação" msgid "NotificationEvent|Close issue" -msgstr "NotificationEvent|Fechar issue" +msgstr "Fechar issue" msgid "NotificationEvent|Close merge request" -msgstr "NotificationEvent|Fechar merge request" +msgstr "Fechar merge request" msgid "NotificationEvent|Failed pipeline" -msgstr "NotificationEvent|Falha no pipeline" +msgstr "Falha no pipeline" msgid "NotificationEvent|Merge merge request" -msgstr "NotificationEvent|Aceitar merge request" +msgstr "Aceitar merge request" msgid "NotificationEvent|New issue" -msgstr "NotificationEvent|Nova issue" +msgstr "Nova issue" msgid "NotificationEvent|New merge request" -msgstr "NotificationEvent|Novo merge request" +msgstr "Novo merge request" msgid "NotificationEvent|New note" -msgstr "NotificationEvent|Novo comentário" +msgstr "Novo comentário" msgid "NotificationEvent|Reassign issue" -msgstr "NotificationEvent|Reatribuir issue" +msgstr "Reatribuir issue" msgid "NotificationEvent|Reassign merge request" -msgstr "NotificationEvent|Reatribuir merge request" +msgstr "Reatribuir merge request" msgid "NotificationEvent|Reopen issue" -msgstr "NotificationEvent|Reabrir issue" +msgstr "Reabrir issue" msgid "NotificationEvent|Successful pipeline" -msgstr "NotificationEvent|Pipeline bem sucedido" +msgstr "Pipeline bem sucedido" msgid "NotificationLevel|Custom" -msgstr "NotificationLevel|Personalizar" +msgstr "Personalizar" msgid "NotificationLevel|Disabled" -msgstr "NotificationLevel|Desabilitado" +msgstr "Desabilitado" msgid "NotificationLevel|Global" -msgstr "NotificationLevel|Global" +msgstr "Global" msgid "NotificationLevel|On mention" -msgstr "NotificationLevel|Quando mencionado" +msgstr "Quando mencionado" msgid "NotificationLevel|Participate" -msgstr "NotificationLevel|Participar" +msgstr "Participar" msgid "NotificationLevel|Watch" -msgstr "NotificationLevel|Observar" +msgstr "Observar" msgid "OfSearchInADropdown|Filter" -msgstr "OfSearchInADropdown|Filtrar" +msgstr "Filtrar" msgid "OpenedNDaysAgo|Opened" -msgstr "OpenedNDaysAgo|Aberto" +msgstr "Aberto" msgid "Options" msgstr "Opções" @@ -554,40 +554,40 @@ msgid "Pipeline Schedules" msgstr "Agendamentos da Pipeline" msgid "PipelineSchedules|Activated" -msgstr "PipelineSchedules|Ativado" +msgstr "Ativado" msgid "PipelineSchedules|Active" -msgstr "PipelineSchedules|Ativo" +msgstr "Ativo" msgid "PipelineSchedules|All" -msgstr "PipelineSchedules|Todos" +msgstr "Todos" msgid "PipelineSchedules|Inactive" -msgstr "PipelineSchedules|Inativo" +msgstr "Inativo" msgid "PipelineSchedules|Next Run" -msgstr "PipelineSchedules|Próxima Execução" +msgstr "Próxima Execução" msgid "PipelineSchedules|None" -msgstr "PipelineSchedules|Nenhum" +msgstr "Nenhum" msgid "PipelineSchedules|Provide a short description for this pipeline" -msgstr "PipelineSchedules|Digite uma descrição curta para esta pipeline" +msgstr "Digite uma descrição curta para esta pipeline" msgid "PipelineSchedules|Take ownership" -msgstr "PipelineSchedules|Tornar-se proprietário" +msgstr "Tornar-se proprietário" msgid "PipelineSchedules|Target" -msgstr "PipelineSchedules|Destino" +msgstr "Destino" msgid "PipelineSheduleIntervalPattern|Custom" -msgstr "PipelineSheduleIntervalPattern|Personalizado" +msgstr "Personalizado" msgid "Pipeline|with stage" -msgstr "Pipeline|com etapa" +msgstr "com etapa" msgid "Pipeline|with stages" -msgstr "Pipeline|com etapas" +msgstr "com etapas" msgid "Project '%{project_name}' queued for deletion." msgstr "Projeto'%{project_name}' marcado para exclusão." @@ -627,25 +627,25 @@ msgid "Project home" msgstr "Página inicial do projeto" msgid "ProjectFeature|Disabled" -msgstr "ProjectFeature|Desabilitado" +msgstr "Desabilitado" msgid "ProjectFeature|Everyone with access" -msgstr "ProjectFeature|Todos que possuem acesso" +msgstr "Todos que possuem acesso" msgid "ProjectFeature|Only team members" -msgstr "ProjectFeature|Apenas membros do time" +msgstr "Apenas membros do time" msgid "ProjectFileTree|Name" -msgstr "ProjectFileTree|Nome" +msgstr "Nome" msgid "ProjectLastActivity|Never" -msgstr "ProjectLastActivity|Nunca" +msgstr "Nunca" msgid "ProjectLifecycle|Stage" -msgstr "PipelineSchedules|Etapa" +msgstr "Etapa" msgid "ProjectNetworkGraph|Graph" -msgstr "ProjectNetworkGraph|Árvore" +msgstr "Árvore" msgid "Read more" msgstr "Leia mais" @@ -654,10 +654,10 @@ msgid "Readme" msgstr "Leia-me" msgid "RefSwitcher|Branches" -msgstr "RefSwitcher|Branches" +msgstr "Branches" msgid "RefSwitcher|Tags" -msgstr "RefSwitcher|Tags" +msgstr "Tags" msgid "Related Commits" msgstr "Commits Relacionados" @@ -728,7 +728,7 @@ msgid "Set up auto deploy" msgstr "Configurar implantação automática" msgid "SetPasswordToCloneLink|set a password" -msgstr "SetPasswordToCloneLink|defina uma senha" +msgstr "defina uma senha" msgid "Showing %d event" msgid_plural "Showing %d events" @@ -739,7 +739,7 @@ msgid "Source code" msgstr "Código-fonte" msgid "StarProject|Star" -msgstr "StarProject|Marcar" +msgstr "Marcar" msgid "Start a %{new_merge_request} with these changes" msgstr "Iniciar um %{new_merge_request} a partir dessas alterações" @@ -882,140 +882,140 @@ msgid "Time until first merge request" msgstr "Tempo até a primeira solicitação de incorporação" msgid "Timeago|%s days ago" -msgstr "Timeago|há %s dias" +msgstr "há %s dias" msgid "Timeago|%s days remaining" -msgstr "Timeago|%s dias restantes" +msgstr "%s dias restantes" msgid "Timeago|%s hours remaining" -msgstr "Timeago|%s horas restantes" +msgstr "%s horas restantes" msgid "Timeago|%s minutes ago" -msgstr "Timeago|há %s minutos" +msgstr "há %s minutos" msgid "Timeago|%s minutes remaining" -msgstr "Timeago|%s minutos restantes" +msgstr "%s minutos restantes" msgid "Timeago|%s months ago" -msgstr "Timeago|há %s meses" +msgstr "há %s meses" msgid "Timeago|%s months remaining" -msgstr "Timeago|%s meses restantes" +msgstr "%s meses restantes" msgid "Timeago|%s seconds remaining" -msgstr "Timeago|%s segundos restantes" +msgstr "%s segundos restantes" msgid "Timeago|%s weeks ago" -msgstr "Timeago|há %s semanas" +msgstr "há %s semanas" msgid "Timeago|%s weeks remaining" -msgstr "Timeago|%s semanas restantes" +msgstr "%s semanas restantes" msgid "Timeago|%s years ago" -msgstr "Timeago|há %s anos" +msgstr "há %s anos" msgid "Timeago|%s years remaining" -msgstr "Timeago|%s anos restantes" +msgstr "%s anos restantes" msgid "Timeago|1 day remaining" -msgstr "Timeago|1 dia restante" +msgstr "1 dia restante" msgid "Timeago|1 hour remaining" -msgstr "Timeago|1 hora restante" +msgstr "1 hora restante" msgid "Timeago|1 minute remaining" -msgstr "Timeago|1 minuto restante" +msgstr "1 minuto restante" msgid "Timeago|1 month remaining" -msgstr "Timeago|1 mês restante" +msgstr "1 mês restante" msgid "Timeago|1 week remaining" -msgstr "Timeago|1 semana restante" +msgstr "1 semana restante" msgid "Timeago|1 year remaining" -msgstr "Timeago|1 ano restante" +msgstr "1 ano restante" msgid "Timeago|Past due" -msgstr "Timeago|Venceu" +msgstr "Venceu" msgid "Timeago|a day ago" -msgstr "Timeago|há um dia" +msgstr "há um dia" msgid "Timeago|a month ago" -msgstr "Timeago|há um mês" +msgstr "há um mês" msgid "Timeago|a week ago" -msgstr "Timeago|há uma semana" +msgstr "há uma semana" msgid "Timeago|a while" -msgstr "Timeago|há algum tempo" +msgstr "há algum tempo" msgid "Timeago|a year ago" -msgstr "Timeago|há um ano" +msgstr "há um ano" msgid "Timeago|about %s hours ago" -msgstr "Timeago|há cerca de %s horas" +msgstr "há cerca de %s horas" msgid "Timeago|about a minute ago" -msgstr "Timeago|há cerca de um minuto" +msgstr "há cerca de um minuto" msgid "Timeago|about an hour ago" -msgstr "Timeago|há cerca de uma hora" +msgstr "há cerca de uma hora" msgid "Timeago|in %s days" -msgstr "Timeago|em %s dias" +msgstr "em %s dias" msgid "Timeago|in %s hours" -msgstr "Timeago|em %s horas" +msgstr "em %s horas" msgid "Timeago|in %s minutes" -msgstr "Timeago|em %s minutos" +msgstr "em %s minutos" msgid "Timeago|in %s months" -msgstr "Timeago|em %s meses" +msgstr "em %s meses" msgid "Timeago|in %s seconds" -msgstr "Timeago|em %s segundos" +msgstr "em %s segundos" msgid "Timeago|in %s weeks" -msgstr "Timeago|em %s semanas" +msgstr "em %s semanas" msgid "Timeago|in %s years" -msgstr "Timeago|em %s anos" +msgstr "em %s anos" msgid "Timeago|in 1 day" -msgstr "Timeago|em 1 dia" +msgstr "em 1 dia" msgid "Timeago|in 1 hour" -msgstr "Timeago|em 1 hora" +msgstr "em 1 hora" msgid "Timeago|in 1 minute" -msgstr "Timeago|em 1 minuto" +msgstr "em 1 minuto" msgid "Timeago|in 1 month" -msgstr "Timeago|em 1 mês" +msgstr "em 1 mês" msgid "Timeago|in 1 week" -msgstr "Timeago|em 1 semana" +msgstr "em 1 semana" msgid "Timeago|in 1 year" -msgstr "Timeago|em 1 ano" +msgstr "em 1 ano" msgid "Timeago|less than a minute ago" -msgstr "Timeago|há menos de um minuto" +msgstr "há menos de um minuto" msgid "Time|hr" msgid_plural "Time|hrs" -msgstr[0] "Time|h" -msgstr[1] "Time|hs" +msgstr[0] "h" +msgstr[1] "hs" msgid "Time|min" msgid_plural "Time|mins" -msgstr[0] "Time|min" -msgstr[1] "Time|mins" +msgstr[0] "min" +msgstr[1] "mins" msgid "Time|s" -msgstr "Time|s" +msgstr "s" msgid "Total Time" msgstr "Tempo Total" @@ -1036,13 +1036,13 @@ msgid "Use your global notification setting" msgstr "Utilizar configuração de notificação global" msgid "VisibilityLevel|Internal" -msgstr "VisibilityLevel|Interno" +msgstr "Interno" msgid "VisibilityLevel|Private" -msgstr "VisibilityLevel|Privado" +msgstr "Privado" msgid "VisibilityLevel|Public" -msgstr "VisibilityLevel|Público" +msgstr "Público" msgid "Want to see the data? Please ask an administrator for access." msgstr "Precisa visualizar os dados? Solicite acesso ao administrador." From 49da169d07b2aeea6c1a357f381ebd627cffe556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Fri, 7 Jul 2017 11:28:46 +0800 Subject: [PATCH 14/61] Add zh-TW translation difference of Pipeline Charts --- locale/zh_TW/part.po | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 locale/zh_TW/part.po diff --git a/locale/zh_TW/part.po b/locale/zh_TW/part.po new file mode 100644 index 00000000000..b4871ff2184 --- /dev/null +++ b/locale/zh_TW/part.po @@ -0,0 +1,70 @@ +# Huang Tao , 2017. #zanata +msgid "" +msgstr "" +"Project-Id-Version: gitlab 1.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-15 21:59-0500\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2017-07-06 11:27-0400\n" +"Last-Translator: Huang Tao \n" +"Language-Team: Chinese (Taiwan)\n" +"Language: zh-TW\n" +"X-Generator: Zanata 3.9.6\n" +"Plural-Forms: nplurals=1; plural=0\n" + +msgid "1 pipeline" +msgid_plural "%d pipelines" +msgstr[0] "%d 條流水線" + +msgid "A collection of graphs regarding Continuous Integration" +msgstr "相關持續集成的圖像集合" + +msgid "Commit duration in minutes for last 30 commits" +msgstr "最近30次更動花費的時間(分鐘)" + +msgid "" +"Create a personal access token on your account to pull or push via " +"%{protocol}." +msgstr "在帳戶上建立個人訪問令牌,以通過 %{protocol} 來拉取 (pull) 或推送 (push) 。" + +msgid "CreateTokenToCloneLink|create a personal access token" +msgstr "建立個人訪問令牌" + +msgid "Jobs for last month" +msgstr "上個月的作業" + +msgid "Jobs for last week" +msgstr "上個星期的作業" + +msgid "Jobs for last year" +msgstr "去年的作業" + +msgid "PipelineCharts|Failed:" +msgstr "失敗:" + +msgid "PipelineCharts|Overall statistics" +msgstr "總體統計" + +msgid "PipelineCharts|Success ratio:" +msgstr "成功率:" + +msgid "PipelineCharts|Successful:" +msgstr "成功:" + +msgid "PipelineCharts|Total:" +msgstr "總計:" + +msgid "Pipelines" +msgstr "流水線 (Pipelines) " + +msgid "Pipelines charts" +msgstr "流水線 (Pipelines) 圖表" + +msgid "Pipeline|all" +msgstr "所有" + +msgid "Pipeline|success" +msgstr "成功" + From 4cc4561b572fa9ca37fb0c8bbf91def3ba9e47e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Fri, 7 Jul 2017 11:31:38 +0800 Subject: [PATCH 15/61] Add it translation difference of Pipeline Charts --- locale/it/part.po | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 locale/it/part.po diff --git a/locale/it/part.po b/locale/it/part.po new file mode 100644 index 00000000000..e0423ff493e --- /dev/null +++ b/locale/it/part.po @@ -0,0 +1,71 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: gitlab 1.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-06-15 21:59-0500\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: Italian\n" +"Language: it\n" +"X-Generator: Zanata 3.9.6\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +msgid "1 pipeline" +msgid_plural "%d pipelines" +msgstr[0] "" +msgstr[1] "" + +msgid "A collection of graphs regarding Continuous Integration" +msgstr "" + +msgid "Commit duration in minutes for last 30 commits" +msgstr "" + +msgid "" +"Create a personal access token on your account to pull or push via " +"%{protocol}." +msgstr "" + +msgid "CreateTokenToCloneLink|create a personal access token" +msgstr "" + +msgid "Jobs for last month" +msgstr "" + +msgid "Jobs for last week" +msgstr "" + +msgid "Jobs for last year" +msgstr "" + +msgid "PipelineCharts|Failed:" +msgstr "" + +msgid "PipelineCharts|Overall statistics" +msgstr "" + +msgid "PipelineCharts|Success ratio:" +msgstr "" + +msgid "PipelineCharts|Successful:" +msgstr "" + +msgid "PipelineCharts|Total:" +msgstr "" + +msgid "Pipelines" +msgstr "" + +msgid "Pipelines charts" +msgstr "" + +msgid "Pipeline|all" +msgstr "" + +msgid "Pipeline|success" +msgstr "" + From 3fc2cbf9f677a2860ed985bc8e51c3c6eff362d2 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Fri, 7 Jul 2017 17:21:03 +0200 Subject: [PATCH 16/61] Mor info about prometheus service configuration, and fixing problems with missing labels --- app/views/projects/services/prometheus/_show.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml index 0996ec06ab7..d8e11500964 100644 --- a/app/views/projects/services/prometheus/_show.html.haml +++ b/app/views/projects/services/prometheus/_show.html.haml @@ -8,7 +8,7 @@ %p Metrics are automatically configured and monitored based on a library of metrics from popular exporters. - = link_to 'More information', '#' + = link_to 'More information', help_page_path('user/project/integrations/prometheus') .col-lg-9 .panel.panel-default.js-panel-monitored-metrics{ data: { "active-metrics" => "#{project_prometheus_active_metrics_path(@project, :json)}" } } @@ -41,5 +41,5 @@ %code $CI_ENVIRONMENT_SLUG to exporter’s queries. - = link_to 'More information', '#' + = link_to 'More information', help_page_path('user/project/integrations/prometheus', anchor: 'metrics-and-labels') %ul.list-unstyled.metrics-list.js-missing-var-metrics-list From 96d2ce63acbfe6966ab16daeaf9accd38e8bf453 Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Sat, 8 Jul 2017 20:12:49 +0900 Subject: [PATCH 17/61] Bump scss-lint to 0.54.0 --- .scss-lint.yml | 4 ++++ Gemfile | 2 +- Gemfile.lock | 8 ++++---- changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml | 4 ++++ 4 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml diff --git a/.scss-lint.yml b/.scss-lint.yml index db234ad739c..02fc586a1c4 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -178,6 +178,10 @@ linters: SpaceAfterComma: enabled: false + # Comment literals should be followed by a space. + SpaceAfterComment: + enabled: false + # Properties should be formatted with a single space separating the colon # from the property's value. SpaceAfterPropertyColon: diff --git a/Gemfile b/Gemfile index 2c248a45175..7e6af981c33 100644 --- a/Gemfile +++ b/Gemfile @@ -336,7 +336,7 @@ group :development, :test do gem 'rubocop', '~> 0.47.1', require: false gem 'rubocop-rspec', '~> 1.15.0', require: false - gem 'scss_lint', '~> 0.47.0', require: false + gem 'scss_lint', '~> 0.54.0', require: false gem 'haml_lint', '~> 0.21.0', require: false gem 'simplecov', '~> 0.14.0', require: false gem 'flay', '~> 2.8.0', require: false diff --git a/Gemfile.lock b/Gemfile.lock index f356024506c..cb14649164e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -766,9 +766,9 @@ GEM sawyer (0.8.1) addressable (>= 2.3.5, < 2.6) faraday (~> 0.8, < 1.0) - scss_lint (0.47.1) - rake (>= 0.9, < 11) - sass (~> 3.4.15) + scss_lint (0.54.0) + rake (>= 0.9, < 13) + sass (~> 3.4.20) securecompare (1.0.0) seed-fu (2.3.6) activerecord (>= 3.1) @@ -1087,7 +1087,7 @@ DEPENDENCIES rugged (~> 0.25.1.1) sanitize (~> 2.0) sass-rails (~> 5.0.6) - scss_lint (~> 0.47.0) + scss_lint (~> 0.54.0) seed-fu (~> 2.3.5) select2-rails (~> 3.5.9) sentry-raven (~> 2.5.3) diff --git a/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml b/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml new file mode 100644 index 00000000000..e6cd834aed2 --- /dev/null +++ b/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml @@ -0,0 +1,4 @@ +--- +title: Bump scss-lint to 0.54.0 +merge_request: 12733 +author: Takuya Noguchi From 40cbb345d5b872d993a53a595983c246ad18a7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Mon, 10 Jul 2017 09:32:18 +0800 Subject: [PATCH 18/61] optimize translation based on discussion --- locale/zh_TW/part.po | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locale/zh_TW/part.po b/locale/zh_TW/part.po index b4871ff2184..14eb8cea72f 100644 --- a/locale/zh_TW/part.po +++ b/locale/zh_TW/part.po @@ -7,7 +7,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-07-06 11:27-0400\n" +"PO-Revision-Date: 2017-07-09 09:02-0400\n" "Last-Translator: Huang Tao \n" "Language-Team: Chinese (Taiwan)\n" "Language: zh-TW\n" @@ -19,18 +19,18 @@ msgid_plural "%d pipelines" msgstr[0] "%d 條流水線" msgid "A collection of graphs regarding Continuous Integration" -msgstr "相關持續集成的圖像集合" +msgstr "持續整合 (CI) 相關的圖表" msgid "Commit duration in minutes for last 30 commits" -msgstr "最近30次更動花費的時間(分鐘)" +msgstr "最近 30 次更動花費的時間(分鐘)" msgid "" "Create a personal access token on your account to pull or push via " "%{protocol}." -msgstr "在帳戶上建立個人訪問令牌,以通過 %{protocol} 來拉取 (pull) 或推送 (push) 。" +msgstr "建立個人存取憑證 (access token)以使用 %{protocol} 來上傳 (push) 或下載 (pull) 。" msgid "CreateTokenToCloneLink|create a personal access token" -msgstr "建立個人訪問令牌" +msgstr "建立個人存取憑證 (access token)" msgid "Jobs for last month" msgstr "上個月的作業" @@ -39,7 +39,7 @@ msgid "Jobs for last week" msgstr "上個星期的作業" msgid "Jobs for last year" -msgstr "去年的作業" +msgstr "去年的工作 (job)" msgid "PipelineCharts|Failed:" msgstr "失敗:" @@ -48,7 +48,7 @@ msgid "PipelineCharts|Overall statistics" msgstr "總體統計" msgid "PipelineCharts|Success ratio:" -msgstr "成功率:" +msgstr "成功比率:" msgid "PipelineCharts|Successful:" msgstr "成功:" From 9e4e1afb4a7907f2a79d18fd9b5d03c9f6599ccf Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Mon, 10 Jul 2017 14:54:58 -0500 Subject: [PATCH 19/61] MR branch link now links to tree instead of commits --- app/presenters/merge_request_presenter.rb | 2 +- changelogs/unreleased/mr-branch-link-use-tree.yml | 4 ++++ spec/presenters/merge_request_presenter_spec.rb | 13 +++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/mr-branch-link-use-tree.yml diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 6ba1d3165e9..101568b66b7 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -94,7 +94,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated if source_branch_exists? namespace = link_to(namespace, project_path(source_project)) - branch = link_to(branch, project_commits_path(source_project, source_branch)) + branch = link_to(branch, project_tree_path(source_project, source_branch)) end if for_fork? diff --git a/changelogs/unreleased/mr-branch-link-use-tree.yml b/changelogs/unreleased/mr-branch-link-use-tree.yml new file mode 100644 index 00000000000..f4c4d9f5082 --- /dev/null +++ b/changelogs/unreleased/mr-branch-link-use-tree.yml @@ -0,0 +1,4 @@ +--- +title: MR branch link now links to tree instead of commits +merge_request: +author: diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index f5a14b1d04d..40fe9e3c004 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -363,4 +363,17 @@ describe MergeRequestPresenter do end end end + + describe '#source_branch_with_namespace_link' do + subject do + described_class.new(resource, current_user: user).source_branch_with_namespace_link + end + + it 'returns link' do + allow(resource).to receive(:source_branch_exists?) { true } + + is_expected + .to eq("#{resource.source_branch}") + end + end end From a646f3cf5de54e57d8869482d7d4c544de788c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Tue, 11 Jul 2017 10:14:57 +0800 Subject: [PATCH 20/61] merge pipeline charts translate to gitlab.po --- locale/zh_TW/gitlab.po | 58 ++++++++++++++++++++++++++++++++-- locale/zh_TW/part.po | 70 ------------------------------------------ 2 files changed, 56 insertions(+), 72 deletions(-) delete mode 100644 locale/zh_TW/part.po diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po index fa0b3b339fa..54cbe3c59c1 100644 --- a/locale/zh_TW/gitlab.po +++ b/locale/zh_TW/gitlab.po @@ -7,11 +7,11 @@ msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-19 15:50-0500\n" +"POT-Creation-Date: 2017-06-28 13:32+0200\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-06-28 11:13-0400\n" +"PO-Revision-Date: 2017-07-10 09:55-0400\n" "Last-Translator: Huang Tao \n" "Language-Team: Chinese (Taiwan) (https://translate.zanata.org/project/view/GitLab)\n" "Language: zh-TW\n" @@ -30,6 +30,13 @@ msgstr[0] "%d 個更動 (commit)" msgid "%{commit_author_link} committed %{commit_timeago}" msgstr "%{commit_author_link} 在 %{commit_timeago} 送交" +msgid "1 pipeline" +msgid_plural "%d pipelines" +msgstr[0] "%d 條流水線" + +msgid "A collection of graphs regarding Continuous Integration" +msgstr "持續整合 (CI) 相關的圖表" + msgid "About auto deploy" msgstr "關於自動部署" @@ -187,6 +194,9 @@ msgid "Commit" msgid_plural "Commits" msgstr[0] "更動記錄 (commit) " +msgid "Commit duration in minutes for last 30 commits" +msgstr "最近 30 次更動花費的時間(分鐘)" + msgid "Commit message" msgstr "更動說明 (commit) " @@ -226,6 +236,11 @@ msgstr "複製更動記錄 (commit) 的 SHA 值到剪貼簿" msgid "Create New Directory" msgstr "建立新目錄" +msgid "" +"Create a personal access token on your account to pull or push via " +"%{protocol}." +msgstr "建立個人存取憑證 (access token) 以使用 %{protocol} 來上傳 (push) 或下載 (pull) 。" + msgid "Create directory" msgstr "建立目錄" @@ -244,6 +259,9 @@ msgstr "分支 (fork) " msgid "CreateTag|Tag" msgstr "建立標籤" +msgid "CreateTokenToCloneLink|create a personal access token" +msgstr "建立個人存取憑證 (access token)" + msgid "Cron Timezone" msgstr "Cron 時區" @@ -408,6 +426,15 @@ msgstr "循環週期" msgid "Introducing Cycle Analytics" msgstr "週期分析簡介" +msgid "Jobs for last month" +msgstr "上個月的作業" + +msgid "Jobs for last week" +msgstr "上個星期的作業" + +msgid "Jobs for last year" +msgstr "去年的任務 (job)" + msgid "LFSStatus|Disabled" msgstr "停用" @@ -570,6 +597,21 @@ msgstr "流水線 (pipeline) 排程" msgid "Pipeline Schedules" msgstr "流水線 (pipeline) 排程" +msgid "PipelineCharts|Failed:" +msgstr "失敗:" + +msgid "PipelineCharts|Overall statistics" +msgstr "總體統計" + +msgid "PipelineCharts|Success ratio:" +msgstr "成功比率:" + +msgid "PipelineCharts|Successful:" +msgstr "成功:" + +msgid "PipelineCharts|Total:" +msgstr "總計:" + msgid "PipelineSchedules|Activated" msgstr "是否啟用" @@ -600,6 +642,18 @@ msgstr "目標" msgid "PipelineSheduleIntervalPattern|Custom" msgstr "自訂" +msgid "Pipelines" +msgstr "流水線 (Pipelines) " + +msgid "Pipelines charts" +msgstr "流水線 (Pipelines) 圖表" + +msgid "Pipeline|all" +msgstr "所有" + +msgid "Pipeline|success" +msgstr "成功" + msgid "Pipeline|with stage" msgstr "於階段" diff --git a/locale/zh_TW/part.po b/locale/zh_TW/part.po deleted file mode 100644 index 14eb8cea72f..00000000000 --- a/locale/zh_TW/part.po +++ /dev/null @@ -1,70 +0,0 @@ -# Huang Tao , 2017. #zanata -msgid "" -msgstr "" -"Project-Id-Version: gitlab 1.0.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-15 21:59-0500\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-07-09 09:02-0400\n" -"Last-Translator: Huang Tao \n" -"Language-Team: Chinese (Taiwan)\n" -"Language: zh-TW\n" -"X-Generator: Zanata 3.9.6\n" -"Plural-Forms: nplurals=1; plural=0\n" - -msgid "1 pipeline" -msgid_plural "%d pipelines" -msgstr[0] "%d 條流水線" - -msgid "A collection of graphs regarding Continuous Integration" -msgstr "持續整合 (CI) 相關的圖表" - -msgid "Commit duration in minutes for last 30 commits" -msgstr "最近 30 次更動花費的時間(分鐘)" - -msgid "" -"Create a personal access token on your account to pull or push via " -"%{protocol}." -msgstr "建立個人存取憑證 (access token)以使用 %{protocol} 來上傳 (push) 或下載 (pull) 。" - -msgid "CreateTokenToCloneLink|create a personal access token" -msgstr "建立個人存取憑證 (access token)" - -msgid "Jobs for last month" -msgstr "上個月的作業" - -msgid "Jobs for last week" -msgstr "上個星期的作業" - -msgid "Jobs for last year" -msgstr "去年的工作 (job)" - -msgid "PipelineCharts|Failed:" -msgstr "失敗:" - -msgid "PipelineCharts|Overall statistics" -msgstr "總體統計" - -msgid "PipelineCharts|Success ratio:" -msgstr "成功比率:" - -msgid "PipelineCharts|Successful:" -msgstr "成功:" - -msgid "PipelineCharts|Total:" -msgstr "總計:" - -msgid "Pipelines" -msgstr "流水線 (Pipelines) " - -msgid "Pipelines charts" -msgstr "流水線 (Pipelines) 圖表" - -msgid "Pipeline|all" -msgstr "所有" - -msgid "Pipeline|success" -msgstr "成功" - From c0e6e9981f85248f2d66338ca5918006f4316dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Tue, 11 Jul 2017 18:45:17 +0800 Subject: [PATCH 21/61] optimize translation content based on discussion --- locale/zh_TW/gitlab.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po index 54cbe3c59c1..c2764427cb6 100644 --- a/locale/zh_TW/gitlab.po +++ b/locale/zh_TW/gitlab.po @@ -11,7 +11,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-07-10 09:55-0400\n" +"PO-Revision-Date: 2017-07-11 05:14-0400\n" "Last-Translator: Huang Tao \n" "Language-Team: Chinese (Taiwan) (https://translate.zanata.org/project/view/GitLab)\n" "Language: zh-TW\n" @@ -427,13 +427,13 @@ msgid "Introducing Cycle Analytics" msgstr "週期分析簡介" msgid "Jobs for last month" -msgstr "上個月的作業" +msgstr "上個月的任務 (job) " msgid "Jobs for last week" -msgstr "上個星期的作業" +msgstr "上個星期的任務 (job) " msgid "Jobs for last year" -msgstr "去年的任務 (job)" +msgstr "去年的任務 (job) " msgid "LFSStatus|Disabled" msgstr "停用" @@ -646,7 +646,7 @@ msgid "Pipelines" msgstr "流水線 (Pipelines) " msgid "Pipelines charts" -msgstr "流水線 (Pipelines) 圖表" +msgstr "流水線 (Pipelines) 圖表" msgid "Pipeline|all" msgstr "所有" From 09193a4fe18044a61021afef1282ec60b81810b1 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 11 Jul 2017 09:48:59 -0500 Subject: [PATCH 22/61] Convert target branch link to use tree --- .../vue_merge_request_widget/stores/mr_widget_store.js | 2 +- app/presenters/merge_request_presenter.rb | 4 ++-- app/serializers/merge_request_entity.rb | 4 ++-- spec/fixtures/api/schemas/entities/merge_request.json | 2 +- spec/presenters/merge_request_presenter_spec.rb | 6 +++--- spec/serializers/merge_request_entity_spec.rb | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 69bc1436284..d4ef5972ce0 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -47,7 +47,7 @@ export default class MergeRequestStore { this.sourceBranchPath = data.source_branch_path; this.sourceBranchLink = data.source_branch_with_namespace_link; this.mergeError = data.merge_error; - this.targetBranchPath = data.target_branch_commits_path; + this.targetBranchPath = data.target_branch_tree_path; this.conflictResolutionPath = data.conflict_resolution_path; this.cancelAutoMergePath = data.cancel_merge_when_pipeline_succeeds_path; this.removeWIPPath = data.remove_wip_path; diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 101568b66b7..4084a982071 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -76,9 +76,9 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated end end - def target_branch_commits_path + def target_branch_tree_path if target_branch_exists? - project_commits_path(project, target_branch) + project_tree_path(project, target_branch) end end diff --git a/app/serializers/merge_request_entity.rb b/app/serializers/merge_request_entity.rb index 7ec2dbd0efe..fb6709699a7 100644 --- a/app/serializers/merge_request_entity.rb +++ b/app/serializers/merge_request_entity.rb @@ -93,8 +93,8 @@ class MergeRequestEntity < IssuableEntity # Paths # - expose :target_branch_commits_path do |merge_request| - presenter(merge_request).target_branch_commits_path + expose :target_branch_tree_path do |merge_request| + presenter(merge_request).target_branch_tree_path end expose :new_blob_path do |merge_request| diff --git a/spec/fixtures/api/schemas/entities/merge_request.json b/spec/fixtures/api/schemas/entities/merge_request.json index b6a59a6cc47..b6cda963ffa 100644 --- a/spec/fixtures/api/schemas/entities/merge_request.json +++ b/spec/fixtures/api/schemas/entities/merge_request.json @@ -74,7 +74,7 @@ }, "additionalProperties": false }, - "target_branch_commits_path": { "type": "string" }, + "target_branch_tree_path": { "type": "string" }, "source_branch_path": { "type": "string" }, "conflict_resolution_path": { "type": ["string", "null"] }, "cancel_merge_when_pipeline_succeeds_path": { "type": "string" }, diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index 40fe9e3c004..ef12611cff8 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -317,10 +317,10 @@ describe MergeRequestPresenter do end end - describe '#target_branch_commits_path' do + describe '#target_branch_tree_path' do subject do described_class.new(resource, current_user: user) - .target_branch_commits_path + .target_branch_tree_path end context 'when target branch exists' do @@ -328,7 +328,7 @@ describe MergeRequestPresenter do allow(resource).to receive(:target_branch_exists?) { true } is_expected - .to eq("/#{resource.target_project.full_path}/commits/#{resource.target_branch}") + .to eq("/#{resource.target_project.full_path}/tree/#{resource.target_branch}") end end diff --git a/spec/serializers/merge_request_entity_spec.rb b/spec/serializers/merge_request_entity_spec.rb index d38433c2365..0c1db82aa55 100644 --- a/spec/serializers/merge_request_entity_spec.rb +++ b/spec/serializers/merge_request_entity_spec.rb @@ -46,7 +46,7 @@ describe MergeRequestEntity do :conflict_resolution_path, :cancel_merge_when_pipeline_succeeds_path, :create_issue_to_resolve_discussions_path, - :source_branch_path, :target_branch_commits_path, + :source_branch_path, :target_branch_tree_path, :commits_count) end From 08ce213c410aa6c6d48fddc2de79accc094564a9 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Mon, 10 Jul 2017 05:43:20 +0200 Subject: [PATCH 23/61] Migrate Workhorse SendBlob to Gitaly --- GITLAB_WORKHORSE_VERSION | 2 +- lib/gitlab/workhorse.rb | 26 +++++++++++++++++---- spec/lib/gitlab/workhorse_spec.rb | 38 +++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 276cbf9e285..4a36342fcab 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -2.3.0 +3.0.0 diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 4aef23b6aee..d4829272c93 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -62,10 +62,21 @@ module Gitlab end def send_git_blob(repository, blob) - params = { - 'RepoPath' => repository.path_to_repo, - 'BlobId' => blob.id - } + params = if Gitlab::GitalyClient.feature_enabled?(:project_raw_show) + { + 'GitalyServer' => gitaly_server_hash(repository), + 'GetBlobRequest' => { + repository: repository.gitaly_repository.to_h, + oid: blob.id, + limit: -1 + } + } + else + { + 'RepoPath' => repository.path_to_repo, + 'BlobId' => blob.id + } + end [ SEND_DATA_HEADER, @@ -192,6 +203,13 @@ module Gitlab def encode(hash) Base64.urlsafe_encode64(JSON.dump(hash)) end + + def gitaly_server_hash(repository) + { + address: Gitlab::GitalyClient.address(repository.project.repository_storage), + token: Gitlab::GitalyClient.token(repository.project.repository_storage) + } + end end end end diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb index 493ff3bb5fb..1bcd0681621 100644 --- a/spec/lib/gitlab/workhorse_spec.rb +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -317,4 +317,42 @@ describe Gitlab::Workhorse, lib: true do end end end + + describe '.send_git_blob' do + include FakeBlobHelpers + + let(:blob) { fake_blob } + + subject { described_class.send_git_blob(repository, blob) } + + context 'when Gitaly project_raw_show feature is enabled' do + it 'sets the header correctly' do + key, command, params = decode_workhorse_header(subject) + + expect(key).to eq('Gitlab-Workhorse-Send-Data') + expect(command).to eq('git-blob') + expect(params).to eq({ + 'GitalyServer' => { + address: Gitlab::GitalyClient.address(project.repository_storage), + token: Gitlab::GitalyClient.token(project.repository_storage) + }, + 'GetBlobRequest' => { + repository: repository.gitaly_repository.to_h, + oid: blob.id, + limit: -1 + } + }.deep_stringify_keys) + end + end + + context 'when Gitaly project_raw_show feature is disabled', skip_gitaly_mock: true do + it 'sets the header correctly' do + key, command, params = decode_workhorse_header(subject) + + expect(key).to eq('Gitlab-Workhorse-Send-Data') + expect(command).to eq('git-blob') + expect(params).to eq('RepoPath' => repository.path_to_repo, 'BlobId' => blob.id) + end + end + end end From 6eeb6384349b19ec21b667a080893e4facd9b591 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 11 Jul 2017 11:49:22 -0500 Subject: [PATCH 24/61] Make commits behind text a link to the target branch commits page --- .../components/mr_widget_header.js | 4 ++-- .../stores/mr_widget_store.js | 3 ++- app/presenters/merge_request_presenter.rb | 6 +++++ app/serializers/merge_request_entity.rb | 4 ++++ .../api/schemas/entities/merge_request.json | 1 + .../components/mr_widget_header_spec.js | 7 ++++-- .../merge_request_presenter_spec.rb | 24 +++++++++++++++++++ spec/serializers/merge_request_entity_spec.rb | 4 ++-- 8 files changed, 46 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js index f8b3fb748ae..8430548903c 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.js @@ -92,13 +92,13 @@ export default { :class="{'label-truncated has-tooltip': isBranchTitleLong(mr.targetBranch)}" :title="isBranchTitleLong(mr.targetBranch) ? mr.targetBranch : ''" data-placement="bottom"> - {{mr.targetBranch}} + {{mr.targetBranch}} - ({{mr.divergedCommitsCount}} {{commitsText}} behind) + ({{mr.divergedCommitsCount}} {{commitsText}} behind) diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index d4ef5972ce0..72a13108404 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -47,7 +47,8 @@ export default class MergeRequestStore { this.sourceBranchPath = data.source_branch_path; this.sourceBranchLink = data.source_branch_with_namespace_link; this.mergeError = data.merge_error; - this.targetBranchPath = data.target_branch_tree_path; + this.targetBranchPath = data.target_branch_commits_path; + this.targetBranchTreePath = data.target_branch_tree_path; this.conflictResolutionPath = data.conflict_resolution_path; this.cancelAutoMergePath = data.cancel_merge_when_pipeline_succeeds_path; this.removeWIPPath = data.remove_wip_path; diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 4084a982071..2df84e58575 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -82,6 +82,12 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated end end + def target_branch_commits_path + if target_branch_exists? + project_commits_path(project, target_branch) + end + end + def source_branch_path if source_branch_exists? project_branch_path(source_project, source_branch) diff --git a/app/serializers/merge_request_entity.rb b/app/serializers/merge_request_entity.rb index fb6709699a7..7f17f2bf604 100644 --- a/app/serializers/merge_request_entity.rb +++ b/app/serializers/merge_request_entity.rb @@ -93,6 +93,10 @@ class MergeRequestEntity < IssuableEntity # Paths # + expose :target_branch_commits_path do |merge_request| + presenter(merge_request).target_branch_commits_path + end + expose :target_branch_tree_path do |merge_request| presenter(merge_request).target_branch_tree_path end diff --git a/spec/fixtures/api/schemas/entities/merge_request.json b/spec/fixtures/api/schemas/entities/merge_request.json index b6cda963ffa..7ffa82fc4bd 100644 --- a/spec/fixtures/api/schemas/entities/merge_request.json +++ b/spec/fixtures/api/schemas/entities/merge_request.json @@ -74,6 +74,7 @@ }, "additionalProperties": false }, + "target_branch_commits_path": { "type": "string" }, "target_branch_tree_path": { "type": "string" }, "source_branch_path": { "type": "string" }, "conflict_resolution_path": { "type": ["string", "null"] }, diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js index 7f3eea7d2e5..06f89fabf42 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js @@ -54,6 +54,7 @@ describe('MRWidgetHeader', () => { sourceBranch: 'mr-widget-refactor', sourceBranchLink: `mr-widget-refactor`, targetBranchPath: 'foo/bar/commits-path', + targetBranchTreePath: 'foo/bar/tree/path', targetBranch: 'master', isOpen: true, emailPatchesPath: '/mr/email-patches', @@ -69,12 +70,14 @@ describe('MRWidgetHeader', () => { expect(el.classList.contains('mr-source-target')).toBeTruthy(); const sourceBranchLink = el.querySelectorAll('.label-branch')[0]; const targetBranchLink = el.querySelectorAll('.label-branch')[1]; + const commitsCount = el.querySelector('.diverged-commits-count'); expect(sourceBranchLink.textContent).toContain(mr.sourceBranch); expect(targetBranchLink.textContent).toContain(mr.targetBranch); expect(sourceBranchLink.querySelector('a').getAttribute('href')).toEqual(sourceBranchPath); - expect(targetBranchLink.querySelector('a').getAttribute('href')).toEqual(mr.targetBranchPath); - expect(el.querySelector('.diverged-commits-count').textContent).toContain('12 commits behind'); + expect(targetBranchLink.querySelector('a').getAttribute('href')).toEqual(mr.targetBranchTreePath); + expect(commitsCount.textContent).toContain('12 commits behind'); + expect(commitsCount.querySelector('a').getAttribute('href')).toEqual(mr.targetBranchPath); expect(el.textContent).toContain('Check out branch'); expect(el.querySelectorAll('.dropdown li a')[0].getAttribute('href')).toEqual(mr.emailPatchesPath); diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index ef12611cff8..ca6c67a6235 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -317,6 +317,30 @@ describe MergeRequestPresenter do end end + describe '#target_branch_commits_path' do + subject do + described_class.new(resource, current_user: user) + .target_branch_commits_path + end + + context 'when target branch exists' do + it 'returns path' do + allow(resource).to receive(:target_branch_exists?) { true } + + is_expected + .to eq("/#{resource.target_project.full_path}/commits/#{resource.target_branch}") + end + end + + context 'when target branch does not exists' do + it 'returns nil' do + allow(resource).to receive(:target_branch_exists?) { false } + + is_expected.to be_nil + end + end + end + describe '#target_branch_tree_path' do subject do described_class.new(resource, current_user: user) diff --git a/spec/serializers/merge_request_entity_spec.rb b/spec/serializers/merge_request_entity_spec.rb index 0c1db82aa55..b3d58b2636f 100644 --- a/spec/serializers/merge_request_entity_spec.rb +++ b/spec/serializers/merge_request_entity_spec.rb @@ -46,8 +46,8 @@ describe MergeRequestEntity do :conflict_resolution_path, :cancel_merge_when_pipeline_succeeds_path, :create_issue_to_resolve_discussions_path, - :source_branch_path, :target_branch_tree_path, - :commits_count) + :source_branch_path, :target_branch_commits_path, + :target_branch_tree_path, :commits_count) end it 'has email_patches_path' do From 8119c444b319bcf4a8305437a648ec630969d251 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 11 Jul 2017 16:06:38 -0500 Subject: [PATCH 25/61] Add namespace for Blob --- lib/gitlab/git/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index e51966313d4..26581a3cc1b 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -930,7 +930,7 @@ module Gitlab return unless commit_object && commit_object.type == :COMMIT - gitmodules = gitaly_commit_client.tree_entry(ref, '.gitmodules', Blob::MAX_DATA_DISPLAY_SIZE) + gitmodules = gitaly_commit_client.tree_entry(ref, '.gitmodules', Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE) found_module = GitmodulesParser.new(gitmodules.data).parse[path] found_module && found_module['url'] From bf31a7e986f0615b0c090e68c94c5065b00ab3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Tue, 11 Jul 2017 21:38:32 +0000 Subject: [PATCH 26/61] Use Gitaly server v0.17.0 Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/34853 and enables https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/1712 --- GITALY_SERVER_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 04a373efe6b..c5523bd09b1 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.16.0 +0.17.0 From 325191dd4cde7fef3c6c2db340e5acf78247a365 Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Sun, 9 Jul 2017 17:30:05 +0900 Subject: [PATCH 27/61] Enable UnnecessaryParentReference in scss-lint --- .scss-lint.yml | 2 +- app/assets/stylesheets/framework/filters.scss | 4 ++-- app/assets/stylesheets/framework/highlight.scss | 2 +- app/assets/stylesheets/pages/merge_requests.scss | 2 +- app/assets/stylesheets/pages/notes.scss | 2 +- app/assets/stylesheets/pages/pipeline_schedules.scss | 4 ++-- app/assets/stylesheets/pages/projects.scss | 4 ++-- app/assets/stylesheets/pages/todos.scss | 2 +- app/assets/stylesheets/pages/wiki.scss | 4 ++-- .../enable-scss-lint-unnecessary-parent-reference.yml | 4 ++++ 10 files changed, 17 insertions(+), 13 deletions(-) create mode 100644 changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml diff --git a/.scss-lint.yml b/.scss-lint.yml index db234ad739c..da751bc1c58 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -240,7 +240,7 @@ linters: # Do not use parent selector references (&) when they would otherwise # be unnecessary. UnnecessaryParentReference: - enabled: false + enabled: true # URLs should be valid and not contain protocols or domain names. UrlFormat: diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index f05348ee4e3..7e4e5fd7f1c 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -368,7 +368,7 @@ margin-right: 0.3em; } - & > .value { + > .value { font-weight: 600; } } @@ -467,7 +467,7 @@ -webkit-flex-direction: column; flex-direction: column; - &> span { + > span { white-space: normal; word-break: break-all; } diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss index 6d27d7568cf..71d5949b023 100644 --- a/app/assets/stylesheets/framework/highlight.scss +++ b/app/assets/stylesheets/framework/highlight.scss @@ -61,7 +61,7 @@ &:focus { outline: none; - & i { + i { visibility: visible; } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 7adf17dddb8..a8e72f13136 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -96,7 +96,7 @@ overflow: visible; } - & > span { + > span { padding-right: 4px; } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 303425041df..64a48e226bc 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -250,7 +250,7 @@ ul.notes { } .note-text { - & p:first-child { + p:first-child { display: none; } diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss index dc719a6ba94..284b38ad370 100644 --- a/app/assets/stylesheets/pages/pipeline_schedules.scss +++ b/app/assets/stylesheets/pages/pipeline_schedules.scss @@ -96,12 +96,12 @@ } &:last-child { - & .pipeline-variable-row-remove-button { + .pipeline-variable-row-remove-button { display: none; } @media (max-width: $screen-sm-max) { - & .pipeline-variable-value-input { + .pipeline-variable-value-input { margin-right: $pipeline-variable-remove-button-width; } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 7d7c34115f9..46434eab8f3 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -26,7 +26,7 @@ margin-bottom: 5px; } - & > .form-group { + > .form-group { padding-left: 0; } @@ -83,7 +83,7 @@ border: 1px solid $border-color; } - & + .select2 a { + + .select2 a { border-top-left-radius: 0; border-bottom-left-radius: 0; } diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index de652a79369..d7a9dda3770 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -81,7 +81,7 @@ .todo-title { display: flex; - & > .title-item { + > .title-item { -webkit-flex: 0 0 auto; flex: 0 0 auto; margin: 0 2px; diff --git a/app/assets/stylesheets/pages/wiki.scss b/app/assets/stylesheets/pages/wiki.scss index 94d0a39f397..45c21c5d274 100644 --- a/app/assets/stylesheets/pages/wiki.scss +++ b/app/assets/stylesheets/pages/wiki.scss @@ -147,13 +147,13 @@ } ul.wiki-pages-list.content-list { - & ul { + ul { list-style: none; margin-left: 0; padding-left: 15px; } - & ul li { + ul li { padding: 5px 0; } } diff --git a/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml b/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml new file mode 100644 index 00000000000..59d5df56525 --- /dev/null +++ b/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml @@ -0,0 +1,4 @@ +--- +title: Enable UnnecessaryParentReference in scss-lint +merge_request: 12738 +author: Takuya Noguchi From df3109ad75fb7dfac9137692c35cb6a7bbd88e6c Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Wed, 12 Jul 2017 10:09:15 +0900 Subject: [PATCH 28/61] Remove public/ci/favicon.ico --- .../34978-remove-public-ci-favicon-ico.yml | 4 ++++ public/ci/favicon.ico | Bin 5430 -> 0 bytes 2 files changed, 4 insertions(+) create mode 100644 changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml delete mode 100644 public/ci/favicon.ico diff --git a/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml b/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml new file mode 100644 index 00000000000..25cc8b5e45f --- /dev/null +++ b/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml @@ -0,0 +1,4 @@ +--- +title: Remove public/ci/favicon.ico +merge_request: 12803 +author: Takuya Noguchi diff --git a/public/ci/favicon.ico b/public/ci/favicon.ico deleted file mode 100644 index 9663d4d00b9ceee236ba324738d5d4a253a81ed8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5430 zcmc(jPiWLf6vuySOqUQA6-kpdNMl2^n`PU^r35K<1NNeqQc@|!Lk~UJ)I%vAN)JU# zkswsXrW)3*cnHBtktp$8jEu%V=>T3SL0LBiruL_!b=+t2rxdE3b^yJoivUHJOm zym|lT&6}BD41!p&A=tb*;MWnnzcC1QitAVze}nuqvKJUiMdDcaZxHk$kN!%fQY?yG zTe?9qQJ;_MRT`t800UqQ6dkTPS)!7S$J`5g$y%F1HWb%Eca4Tp=|4QL@@CeLU`wQD_{(z|do)^g!ykQw@UV|PPLFu&T{vuxPnO7XuV*<#RAYQWOsQ#0VgP>G; z66l`k0DZvjnd9NzguwgNnOA;5 z%Z!J?x_ee7hgNLoolp6aZ{?DC{rS|UxAyI5KKwyj{O~|qT>QR{)E4Ga;1ZCo+58Q^ z71W#uy6r%3fvtNAKI!LqtdMB>;#xc*9RE78YR`GoWIqiok9+W2efvs0I;wXQm;tgC zPWigrwR^btJ^|l>8xG<>X0F%Q#a4Z4Ij9a*YrvfC`6*{3yA$T`{M3f6F6INM?(Irg zM1D0t6HA=_;TiL1Imq9z`HND;2c1BALiru#eb9S#HxhG}@nwg($lQI#NiPTOh5A8Q zb1slsuIgjO*1mV`4tg3c{u#93%lALVczZN|WIKT7RF@@iFaKLCd>8t*h5cab%FEVb znjgk3z_WxtwiXnZ-?t#={~EdGAkG7fWd{D_+`9(ZwQc-FA@*P>j?vEkF; zB={7xR?EfW;9K{@f{St1aKm&w}-xY!knQ8f##O!&y4e@duA`_ zjbIPs9QYNe1`|%dydGqeZf?eluRd0cHRlG|n{Mtt=Pm90z3qHhougF!^$^^y5dVg= zovt(f1LE8I-&rTV<+D&B{&i>T*MG*XaU9wN%KZZ0@8%v*e_OxyxR-CyY>1V2Gm9*W zl&#SyI(o~LU-7_8Yx-}QSkeC5h3ptO3R=w1f2G9L`P04QpT8u&wg19Z`G$sfN~Jho z{i%II+CqPHI*WYk?~)yFnrblTe1>&^*Itz0TzH*L$wq#nfA9G@EHhS54m;?6u(+agdb7+P zUsFJ5PitTE{&-GdeEIKrd0%ZlO3~j0l<%4xq|4g0 zAG()yHg!JR$A`{^&Zh1Me{Fs&@#=A59CX&R=4$!irx92^THy!4D7X$L q9mJ0S&4s-W)p@R|-qm9Ja(tEFYF}Q7f0}VC`G1-+@4o{67xo{N(2SS> From 8a89738f451060ef4f3620ff3b44872494197735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 12 Jul 2017 09:15:28 +0800 Subject: [PATCH 29/61] Synchronous zanata in zh_TW translation --- locale/zh_TW/gitlab.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po index c2764427cb6..d5a3c5ea0b9 100644 --- a/locale/zh_TW/gitlab.po +++ b/locale/zh_TW/gitlab.po @@ -1,8 +1,8 @@ # Huang Tao , 2017. #zanata -# Lin Jen-Shin , 2017. # Hazel Yang , 2017. # TzeKei Lee , 2017. # Jerry Ho , 2017. +# Lin Jen-Shin , 2017. #zanata msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" @@ -11,8 +11,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-07-11 05:14-0400\n" -"Last-Translator: Huang Tao \n" +"PO-Revision-Date: 2017-07-11 09:10-0400\n" +"Last-Translator: Lin Jen-Shin \n" "Language-Team: Chinese (Taiwan) (https://translate.zanata.org/project/view/GitLab)\n" "Language: zh-TW\n" "X-Generator: Zanata 3.9.6\n" @@ -643,10 +643,10 @@ msgid "PipelineSheduleIntervalPattern|Custom" msgstr "自訂" msgid "Pipelines" -msgstr "流水線 (Pipelines) " +msgstr "流水線 (pipeline) " msgid "Pipelines charts" -msgstr "流水線 (Pipelines) 圖表" +msgstr "流水線 (pipeline) 圖表" msgid "Pipeline|all" msgstr "所有" From bc09ea58d61592867a688dd4d3836e117ab03167 Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Wed, 12 Jul 2017 13:59:39 +0900 Subject: [PATCH 30/61] Enable DeclarationOrder in scss-lint --- .scss-lint.yml | 5 +++-- app/assets/stylesheets/framework/awards.scss | 2 +- app/assets/stylesheets/framework/dropdowns.scss | 4 ++-- app/assets/stylesheets/framework/markdown_area.scss | 2 +- app/assets/stylesheets/framework/responsive-tables.scss | 2 +- app/assets/stylesheets/pages/commits.scss | 2 +- app/assets/stylesheets/pages/cycle_analytics.scss | 8 ++++---- app/assets/stylesheets/pages/diff.scss | 8 ++++---- app/assets/stylesheets/pages/notes.scss | 3 ++- app/assets/stylesheets/pages/pipeline_schedules.scss | 2 +- app/assets/stylesheets/pages/projects.scss | 2 +- app/assets/stylesheets/pages/ui_dev_kit.scss | 8 ++++---- .../unreleased/enable-scss-lint-declaration-order.yml | 4 ++++ 13 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 changelogs/unreleased/enable-scss-lint-declaration-order.yml diff --git a/.scss-lint.yml b/.scss-lint.yml index db234ad739c..389682af3dd 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -43,10 +43,11 @@ linters: # Rule sets should be ordered as follows: # - @extend declarations # - @include declarations without inner @content - # - properties, @include declarations with inner @content + # - properties + # - @include declarations with inner @content # - nested rule sets. DeclarationOrder: - enabled: false + enabled: true # `scss-lint:disable` control comments should be preceded by a comment # explaining why these linters are being disabled for this file. diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss index 19166757e64..72647e3b5e7 100644 --- a/app/assets/stylesheets/framework/awards.scss +++ b/app/assets/stylesheets/framework/awards.scss @@ -231,11 +231,11 @@ .award-control-icon-positive, .award-control-icon-super-positive { + @include transition(opacity, transform); position: absolute; left: 10px; bottom: 6px; opacity: 0; - @include transition(opacity, transform); } .award-control-text { diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index dc4ed42544f..9400127757d 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -35,8 +35,8 @@ .open { .dropdown-menu, .dropdown-menu-nav { - display: block; @include set-visible; + display: block; @media (max-width: $screen-xs-max) { width: 100%; @@ -184,6 +184,7 @@ .dropdown-menu, .dropdown-menu-nav { + @include set-invisible; display: block; position: absolute; width: 100%; @@ -200,7 +201,6 @@ border: 1px solid $dropdown-border-color; border-radius: $border-radius-base; box-shadow: 0 2px 4px $dropdown-shadow-color; - @include set-invisible; @media (max-width: $screen-sm-min) { width: 100%; diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index b21bcc22a87..a2de4598167 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -165,8 +165,8 @@ .cur { .avatar { - border: 1px solid $white-light; @include disableAllAnimation; + border: 1px solid $white-light; } } diff --git a/app/assets/stylesheets/framework/responsive-tables.scss b/app/assets/stylesheets/framework/responsive-tables.scss index d2c90908baa..8e653c443cf 100644 --- a/app/assets/stylesheets/framework/responsive-tables.scss +++ b/app/assets/stylesheets/framework/responsive-tables.scss @@ -100,9 +100,9 @@ } .table-mobile-header { + @include flex-max-width(40); color: $gl-text-color-secondary; text-align: left; - @include flex-max-width(40); @media (min-width: $screen-md-min) { display: none; diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index 9db0f2075cb..a5e4c3311f8 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -250,8 +250,8 @@ } .committed_ago { - float: right; @extend .cgray; + float: right; } } } diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index 3039732ca5b..eeb90759f10 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -24,9 +24,9 @@ .col-headers { ul { + @include clearfix; margin: 0; padding: 0; - @include clearfix; } li { @@ -189,8 +189,8 @@ } li { - list-style-type: none; @include clearfix; + list-style-type: none; } .stage-nav-item { @@ -281,11 +281,11 @@ } .stage-event-item { + @include clearfix; list-style-type: none; padding: 0 0 $gl-padding; margin: 0 $gl-padding $gl-padding; border-bottom: 1px solid $gray-darker; - @include clearfix; &:last-child { border-bottom: none; @@ -307,9 +307,9 @@ &.issue-title, &.commit-title, &.merge-merquest-title { + @include text-overflow(); max-width: 100%; display: block; - @include text-overflow(); a { color: $gl-text-color; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 55011e8a21b..398fd4444ea 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -91,6 +91,7 @@ .old_line, .new_line { + @include user-select(none); margin: 0; border: none; padding: 0 5px; @@ -99,7 +100,6 @@ min-width: 35px; max-width: 50px; width: 35px; - @include user-select(none); a { float: left; @@ -354,12 +354,12 @@ } &.active { + cursor: default; + color: $gl-text-color; + &:hover { text-decoration: none; } - - cursor: default; - color: $gl-text-color; } &.disabled { diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 303425041df..3039f824fb4 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -121,10 +121,11 @@ ul.notes { overflow-y: hidden; .note-text { - word-wrap: break-word; @include md-typography; // Reset ul style types since we're nested inside a ul already @include bulleted-list; + word-wrap: break-word; + ul.task-list { ul:not(.task-list) { padding-left: 1.3em; diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss index dc719a6ba94..a05efd8398d 100644 --- a/app/assets/stylesheets/pages/pipeline_schedules.scss +++ b/app/assets/stylesheets/pages/pipeline_schedules.scss @@ -137,6 +137,7 @@ } .pipeline-variable-row-remove-button { + @include transition(color); flex-shrink: 0; display: flex; justify-content: center; @@ -147,7 +148,6 @@ background: transparent; border: 0; color: $gl-text-color-secondary; - @include transition(color); &:hover, &:focus { diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 7d7c34115f9..74d4ae43ebe 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -587,9 +587,9 @@ pre.light-well { } .project-row { + @include basic-list-stats; display: flex; align-items: center; - @include basic-list-stats; } h3 { diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss index 8c87bc3cafd..798e060a261 100644 --- a/app/assets/stylesheets/pages/ui_dev_kit.scss +++ b/app/assets/stylesheets/pages/ui_dev_kit.scss @@ -5,13 +5,13 @@ } .example { + padding: 15px; + border: 1px dashed $ui-dev-kit-example-border; + margin-bottom: 15px; + &::before { content: "Example"; color: $ui-dev-kit-example-color; } - - padding: 15px; - border: 1px dashed $ui-dev-kit-example-border; - margin-bottom: 15px; } } diff --git a/changelogs/unreleased/enable-scss-lint-declaration-order.yml b/changelogs/unreleased/enable-scss-lint-declaration-order.yml new file mode 100644 index 00000000000..7ac2f55592e --- /dev/null +++ b/changelogs/unreleased/enable-scss-lint-declaration-order.yml @@ -0,0 +1,4 @@ +--- +title: Enable DeclarationOrder in scss-lint +merge_request: 12805 +author: Takuya Noguchi From 29b784257f8da2733813f53879e95802cbf0091e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 12 Jul 2017 08:41:05 +0100 Subject: [PATCH 31/61] Updated new navigation image in preferences Closes #34970 --- app/assets/images/new_nav.png | Bin 23771 -> 14322 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/app/assets/images/new_nav.png b/app/assets/images/new_nav.png index 8879d26d341186a1161a7dd1d83f108ad9fe5b12..f98ca15d787ff70863a5aa44babab172ba0ad648 100644 GIT binary patch literal 14322 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 literal 23771 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 Date: Wed, 12 Jul 2017 09:41:41 +0100 Subject: [PATCH 32/61] Extract the finder portion of ldap_person so it can be overridden in EE --- lib/gitlab/o_auth/user.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb index b3f453e506d..3f2bbd9f6a6 100644 --- a/lib/gitlab/o_auth/user.rb +++ b/lib/gitlab/o_auth/user.rb @@ -101,14 +101,18 @@ module Gitlab # Look for a corresponding person with same uid in any of the configured LDAP providers Gitlab::LDAP::Config.providers.each do |provider| adapter = Gitlab::LDAP::Adapter.new(provider) - @ldap_person = Gitlab::LDAP::Person.find_by_uid(auth_hash.uid, adapter) - # The `uid` might actually be a DN. Try it next. - @ldap_person ||= Gitlab::LDAP::Person.find_by_dn(auth_hash.uid, adapter) + @ldap_person = find_ldap_person(auth_hash, adapter) break if @ldap_person end @ldap_person end + def find_ldap_person(auth_hash, adapter) + by_uid = Gitlab::LDAP::Person.find_by_uid(auth_hash.uid, adapter) + # The `uid` might actually be a DN. Try it next. + by_uid || Gitlab::LDAP::Person.find_by_dn(auth_hash.uid, adapter) + end + def ldap_config Gitlab::LDAP::Config.new(ldap_person.provider) if ldap_person end From 3ef80368839b9d295bfdf2b75b5ced1748884d0d Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 12 Jul 2017 09:45:40 +0100 Subject: [PATCH 33/61] Backport MR create service changes from EE In EE, the `filter_params` method needs the MR to already have its `target_project` assigned. --- app/services/merge_requests/create_service.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 71d37797bb4..19189e64acf 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -7,9 +7,8 @@ module MergeRequests source_project = @project @project = Project.find(params[:target_project_id]) if params[:target_project_id] - params[:target_project_id] ||= source_project.id - merge_request = MergeRequest.new + merge_request.target_project = @project merge_request.source_project = source_project merge_request.source_branch = params[:source_branch] merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) From 545ce888be1af8fa89c91c81b252aff40e4dceef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Wed, 12 Jul 2017 17:51:00 +0800 Subject: [PATCH 34/61] merge Italian translation part.po to gitlab.po --- locale/it/gitlab.po | 73 ++++++++++++++++++++++++++++++++++++++++----- locale/it/part.po | 71 ------------------------------------------- 2 files changed, 65 insertions(+), 79 deletions(-) delete mode 100644 locale/it/part.po diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po index db992021403..c5600721d49 100644 --- a/locale/it/gitlab.po +++ b/locale/it/gitlab.po @@ -4,13 +4,13 @@ msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-19 15:50-0500\n" +"POT-Creation-Date: 2017-06-28 13:32+0200\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2017-07-02 10:32-0400\n" +"PO-Revision-Date: 2017-07-12 05:45-0400\n" "Last-Translator: Paolo Falomo \n" -"Language-Team: Italian\n" +"Language-Team: Italian (https://translate.zanata.org/project/view/GitLab)\n" "Language: it\n" "X-Generator: Zanata 3.9.6\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" @@ -33,6 +33,14 @@ msgstr[1] "%d commit" msgid "%{commit_author_link} committed %{commit_timeago}" msgstr "%{commit_author_link} ha committato %{commit_timeago}" +msgid "1 pipeline" +msgid_plural "%d pipelines" +msgstr[0] "1 pipeline" +msgstr[1] "%d pipeline" + +msgid "A collection of graphs regarding Continuous Integration" +msgstr "Un insieme di grafici riguardo la Continuous Integration" + msgid "About auto deploy" msgstr "Riguardo il rilascio automatico" @@ -196,6 +204,9 @@ msgid_plural "Commits" msgstr[0] "Commit" msgstr[1] "Commits" +msgid "Commit duration in minutes for last 30 commits" +msgstr "Durata del commit (in minuti) per gli ultimi 30 commit" + msgid "Commit message" msgstr "Messaggio del commit" @@ -235,6 +246,13 @@ msgstr "Copia l'SHA del commit negli appunti" msgid "Create New Directory" msgstr "Crea una nuova cartella" +msgid "" +"Create a personal access token on your account to pull or push via " +"%{protocol}." +msgstr "" +"Creare un token di accesso sul tuo account per eseguire pull o push tramite " +"%{protocol}" + msgid "Create directory" msgstr "Crea cartella" @@ -253,6 +271,9 @@ msgstr "Fork" msgid "CreateTag|Tag" msgstr "Tag" +msgid "CreateTokenToCloneLink|create a personal access token" +msgstr "Crea token d'accesso personale" + msgid "Cron Timezone" msgstr "Cron Timezone" @@ -425,6 +446,15 @@ msgstr "Intervallo di Pattern" msgid "Introducing Cycle Analytics" msgstr "Introduzione delle Analisi Cicliche" +msgid "Jobs for last month" +msgstr "Jobs dell'ultimo mese" + +msgid "Jobs for last week" +msgstr "Jobs dell'ultima settimana" + +msgid "Jobs for last year" +msgstr "Jobs dell'ultimo anno" + msgid "LFSStatus|Disabled" msgstr "Disabilitato" @@ -590,6 +620,21 @@ msgstr "Pianificazione Pipeline" msgid "Pipeline Schedules" msgstr "Pianificazione multipla Pipeline" +msgid "PipelineCharts|Failed:" +msgstr "Fallita:" + +msgid "PipelineCharts|Overall statistics" +msgstr "Statistiche riassuntive" + +msgid "PipelineCharts|Success ratio:" +msgstr "Percentuale di successo" + +msgid "PipelineCharts|Successful:" +msgstr "Completata:" + +msgid "PipelineCharts|Total:" +msgstr "Totale:" + msgid "PipelineSchedules|Activated" msgstr "Attivata" @@ -620,6 +665,18 @@ msgstr "Target" msgid "PipelineSheduleIntervalPattern|Custom" msgstr "Personalizzato" +msgid "Pipelines" +msgstr "Pipeline" + +msgid "Pipelines charts" +msgstr "Grafici pipeline" + +msgid "Pipeline|all" +msgstr "tutto" + +msgid "Pipeline|success" +msgstr "successo" + msgid "Pipeline|with stage" msgstr "con stadio" @@ -684,7 +741,7 @@ msgid "ProjectNetworkGraph|Graph" msgstr "Grafico" msgid "Read more" -msgstr "Continua..." +msgstr "Vedi altro" msgid "Readme" msgstr "Leggimi" @@ -751,7 +808,7 @@ msgstr "Seleziona una branch di destinazione" msgid "Set a password on your account to pull or push via %{protocol}." msgstr "" -"Imposta una password sul tuo account per eseguire pull o push tramite " +"Establezca una contraseña en su cuenta para actualizar o enviar a través de " "%{protocol}." msgid "Set up CI" @@ -814,9 +871,9 @@ msgid "" "the issue to a milestone, or add the issue to a list on your Issue Board. " "Begin creating issues to see data for this stage." msgstr "" -"Questo stadio di issue mostra il tempo che ci vuole dal creare un issue " -"all'assegnarli una milestone, o ad aggiungere un issue alla tua board. Crea " -"un issue per vedere questo stadio." +"Lo stadio di Issue mostra il tempo che impiega un issue ad esser correlato " +"ad una Milestone, o ad esser aggiunto ad una tua Lavagna. Inizia la " +"creazione di problemi per visualizzare i dati in questo stadio." msgid "The phase of the development lifecycle." msgstr "Il ciclo vitale della fase di sviluppo." diff --git a/locale/it/part.po b/locale/it/part.po deleted file mode 100644 index e0423ff493e..00000000000 --- a/locale/it/part.po +++ /dev/null @@ -1,71 +0,0 @@ -# -msgid "" -msgstr "" -"Project-Id-Version: gitlab 1.0.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-15 21:59-0500\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: Italian\n" -"Language: it\n" -"X-Generator: Zanata 3.9.6\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -msgid "1 pipeline" -msgid_plural "%d pipelines" -msgstr[0] "" -msgstr[1] "" - -msgid "A collection of graphs regarding Continuous Integration" -msgstr "" - -msgid "Commit duration in minutes for last 30 commits" -msgstr "" - -msgid "" -"Create a personal access token on your account to pull or push via " -"%{protocol}." -msgstr "" - -msgid "CreateTokenToCloneLink|create a personal access token" -msgstr "" - -msgid "Jobs for last month" -msgstr "" - -msgid "Jobs for last week" -msgstr "" - -msgid "Jobs for last year" -msgstr "" - -msgid "PipelineCharts|Failed:" -msgstr "" - -msgid "PipelineCharts|Overall statistics" -msgstr "" - -msgid "PipelineCharts|Success ratio:" -msgstr "" - -msgid "PipelineCharts|Successful:" -msgstr "" - -msgid "PipelineCharts|Total:" -msgstr "" - -msgid "Pipelines" -msgstr "" - -msgid "Pipelines charts" -msgstr "" - -msgid "Pipeline|all" -msgstr "" - -msgid "Pipeline|success" -msgstr "" - From 91f63820a540e7f3e7206dc8044e257cf28527dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 12 Jul 2017 12:18:14 +0200 Subject: [PATCH 35/61] Return `is_admin` attribute in the GET /user endpoint for admins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- .../34325-reinstate-is_admin-for-user-api.yml | 4 +++ doc/api/users.md | 2 +- lib/api/users.rb | 11 +++++- .../api/schemas/public_api/v4/user/admin.json | 34 +++++++++++++++++++ spec/requests/api/users_spec.rb | 8 ++--- 5 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml create mode 100644 spec/fixtures/api/schemas/public_api/v4/user/admin.json diff --git a/changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml b/changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml new file mode 100644 index 00000000000..3bed1fbe16e --- /dev/null +++ b/changelogs/unreleased/34325-reinstate-is_admin-for-user-api.yml @@ -0,0 +1,4 @@ +--- +title: Return `is_admin` attribute in the GET /user endpoint for admins +merge_request: 12811 +author: diff --git a/doc/api/users.md b/doc/api/users.md index 91170e79645..6e5ec3231c5 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -364,7 +364,7 @@ GET /user Parameters: -- `sudo` (required) - the ID of a user +- `sudo` (optional) - the ID of a user to make the call in their place ``` GET /user diff --git a/lib/api/users.rb b/lib/api/users.rb index c469751c31c..81c68ea2658 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -421,7 +421,16 @@ module API success Entities::UserPublic end get do - present current_user, with: sudo? ? Entities::UserWithPrivateDetails : Entities::UserPublic + entity = + if sudo? + Entities::UserWithPrivateDetails + elsif current_user.admin? + Entities::UserWithAdmin + else + Entities::UserPublic + end + + present current_user, with: entity end desc "Get the currently authenticated user's SSH keys" do diff --git a/spec/fixtures/api/schemas/public_api/v4/user/admin.json b/spec/fixtures/api/schemas/public_api/v4/user/admin.json new file mode 100644 index 00000000000..f733914fbf8 --- /dev/null +++ b/spec/fixtures/api/schemas/public_api/v4/user/admin.json @@ -0,0 +1,34 @@ +{ + "type": "object", + "required": [ + "id", + "username", + "email", + "name", + "state", + "avatar_url", + "web_url", + "created_at", + "is_admin", + "bio", + "location", + "skype", + "linkedin", + "twitter", + "website_url", + "organization", + "last_sign_in_at", + "confirmed_at", + "color_scheme_id", + "projects_limit", + "current_sign_in_at", + "identities", + "can_create_group", + "can_create_project", + "two_factor_enabled", + "external" + ], + "properties": { + "$ref": "full.json" + } +} diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index a2368c9d996..877bde3b9a6 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -943,11 +943,11 @@ describe API::Users do expect(response).to have_http_status(403) end - it 'returns initial current user without private token when sudo not defined' do + it 'returns initial current user without private token but with is_admin when sudo not defined' do get api("/user?private_token=#{admin_personal_access_token}") expect(response).to have_http_status(200) - expect(response).to match_response_schema('public_api/v4/user/public') + expect(response).to match_response_schema('public_api/v4/user/admin') expect(json_response['id']).to eq(admin.id) end end @@ -961,11 +961,11 @@ describe API::Users do expect(json_response['id']).to eq(user.id) end - it 'returns initial current user without private token when sudo not defined' do + it 'returns initial current user without private token but with is_admin when sudo not defined' do get api("/user?private_token=#{admin.private_token}") expect(response).to have_http_status(200) - expect(response).to match_response_schema('public_api/v4/user/public') + expect(response).to match_response_schema('public_api/v4/user/admin') expect(json_response['id']).to eq(admin.id) end end From 2c8700c01ee31efd49d8bd54e97e4649e84be7f8 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Wed, 12 Jul 2017 23:45:42 +1100 Subject: [PATCH 36/61] Replace 'browse_files.feature' spinach test with an rspec analog --- .../replace_spinach_spec_browse_files.yml | 4 + features/project/source/browse_files.feature | 323 ------------------ .../projects/user_browses_files_spec.rb | 188 ++++++++++ .../features/projects/user_create_dir_spec.rb | 57 ---- .../projects/user_creates_directory_spec.rb | 87 +++++ .../projects/user_creates_files_spec.rb | 153 +++++++++ .../projects/user_deletes_files_spec.rb | 68 ++++ .../projects/user_edits_files_spec.rb | 122 +++++++ .../projects/user_replaces_files_spec.rb | 87 +++++ .../projects/user_uploads_files_spec.rb | 82 +++++ spec/lib/gitlab/git/hook_spec.rb | 6 + spec/spec_helper.rb | 5 + spec/support/dropzone_helper.rb | 19 ++ 13 files changed, 821 insertions(+), 380 deletions(-) create mode 100644 changelogs/unreleased/replace_spinach_spec_browse_files.yml delete mode 100644 features/project/source/browse_files.feature create mode 100644 spec/features/projects/user_browses_files_spec.rb delete mode 100644 spec/features/projects/user_create_dir_spec.rb create mode 100644 spec/features/projects/user_creates_directory_spec.rb create mode 100644 spec/features/projects/user_creates_files_spec.rb create mode 100644 spec/features/projects/user_deletes_files_spec.rb create mode 100644 spec/features/projects/user_edits_files_spec.rb create mode 100644 spec/features/projects/user_replaces_files_spec.rb create mode 100644 spec/features/projects/user_uploads_files_spec.rb diff --git a/changelogs/unreleased/replace_spinach_spec_browse_files.yml b/changelogs/unreleased/replace_spinach_spec_browse_files.yml new file mode 100644 index 00000000000..7380d39fa9f --- /dev/null +++ b/changelogs/unreleased/replace_spinach_spec_browse_files.yml @@ -0,0 +1,4 @@ +--- +title: Replace 'browse_files.feature' spinach test with an rspec analog +merge_request: 12251 +author: @blackst0ne diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature deleted file mode 100644 index 59a625056d6..00000000000 --- a/features/project/source/browse_files.feature +++ /dev/null @@ -1,323 +0,0 @@ -Feature: Project Source Browse Files - Background: - Given I sign in as a user - And I own project "Shop" - Given I visit project source page - - Scenario: I browse files from master branch - Then I should see files from repository - - Scenario: I browse files for specific ref - Given I visit project source page for "6d39438" - Then I should see files from repository for "6d39438" - - @javascript - Scenario: I browse file content - Given I click on ".gitignore" file in repo - Then I should see its content - - Scenario: I browse raw file - Given I visit blob file from repo - And I click link "Raw" - Then I should see raw file content - - Scenario: I can create file - Given I click on "New file" link in repo - Then I can see new file page - - Scenario: I can create file when I don't have write access - Given I don't have write access - And I click on "New file" link in repo - Then I should see a notice about a new fork having been created - Then I can see new file page - - @javascript - Scenario: I can create and commit file - Given I click on "New file" link in repo - And I edit code - And I fill the new file name - And I fill the commit message - And I click on "Commit changes" - Then I am redirected to the new file - And I should see its new content - - @javascript - Scenario: I can create and commit file when I don't have write access - Given I don't have write access - And I click on "New file" link in repo - And I edit code - And I fill the new file name - And I fill the commit message - And I click on "Commit changes" - Then I am redirected to the fork's new merge request page - And I can see the new commit message - - @javascript - Scenario: I can create and commit file with new lines at the end of file - Given I click on "New file" link in repo - And I edit code with new lines at end of file - And I fill the new file name - And I fill the commit message - And I click on "Commit changes" - Then I am redirected to the new file - And I click button "Edit" - And I should see its content with new lines preserved at end of file - - @javascript - Scenario: I can create and commit file and specify new branch - Given I click on "New file" link in repo - And I edit code - And I fill the new file name - And I fill the commit message - And I fill the new branch name - And I click on "Commit changes" - Then I am redirected to the new merge request page - When I click on "Changes" tab - And I should see its new content - - @javascript - Scenario: I can upload file and commit - Given I click on "Upload file" link in repo - And I upload a new text file - And I fill the upload file commit message - And I fill the new branch name - And I click on "Upload file" - Then I can see the new commit message - And I am redirected to the new merge request page - When I click on "Changes" tab - Then I can see the new text file - - @javascript - Scenario: I can upload file and commit when I don't have write access - Given I don't have write access - And I click on "Upload file" link in repo - Then I should see a notice about a new fork having been created - When I click on "Upload file" link in repo - And I upload a new text file - And I fill the upload file commit message - And I click on "Upload file" - Then I can see the new commit message - And I am redirected to the fork's new merge request page - When I click on "Changes" tab - Then I can see the new text file - - @javascript - Scenario: I can replace file and commit - Given I click on ".gitignore" file in repo - And I see the ".gitignore" - And I click on "Replace" - And I replace it with a text file - And I fill the replace file commit message - And I click on "Replace file" - Then I can see the new text file - And I can see the replacement commit message - - @javascript - Scenario: I can replace file and commit when I don't have write access - Given I don't have write access - And I click on ".gitignore" file in repo - And I see the ".gitignore" - And I click on "Replace" - Then I should see a Fork/Cancel combo - And I click button "Fork" - Then I should see a notice about a new fork having been created - When I click on "Replace" - And I replace it with a text file - And I fill the replace file commit message - And I click on "Replace file" - And I can see the replacement commit message - And I am redirected to the fork's new merge request page - When I click on "Changes" tab - Then I can see the new text file - - @javascript - Scenario: I can create file with a directory name - Given I click on "New file" link in repo - And I fill the new file name with a new directory - And I edit code - And I fill the commit message - And I click on "Commit changes" - Then I am redirected to the new file with directory - And I should see its new content - - @javascript - Scenario: I can edit file - Given I click on ".gitignore" file in repo - And I click button "Edit" - Then I can edit code - - @javascript - Scenario: I can edit file when I don't have write access - Given I don't have write access - And I click on ".gitignore" file in repo - And I click button "Edit" - Then I should see a Fork/Cancel combo - And I click button "Fork" - Then I should see a notice about a new fork having been created - And I can edit code - - Scenario: If the file is binary the edit link is hidden - Given I visit a binary file in the repo - Then I cannot see the edit button - - @javascript - Scenario: I can edit and commit file - Given I click on ".gitignore" file in repo - And I click button "Edit" - And I edit code - And I fill the commit message - And I click on "Commit changes" - Then I am redirected to the ".gitignore" - And I should see its new content - - @javascript - Scenario: I can edit and commit file when I don't have write access - Given I don't have write access - And I click on ".gitignore" file in repo - And I click button "Edit" - Then I should see a Fork/Cancel combo - And I click button "Fork" - And I edit code - And I fill the commit message - And I click on "Commit changes" - Then I am redirected to the fork's new merge request page - And I can see the new commit message - - @javascript - Scenario: I can edit and commit file to new branch - Given I click on ".gitignore" file in repo - And I click button "Edit" - And I edit code - And I fill the commit message - And I fill the new branch name - And I click on "Commit changes" - Then I am redirected to the new merge request page - Then I click on "Changes" tab - And I should see its new content - - @javascript @wip - Scenario: If I don't change the content of the file I see an error message - Given I click on ".gitignore" file in repo - And I click button "edit" - And I fill the commit message - And I click on "Commit changes" - # Test fails because carriage returns are added to the file. - Then I am on the ".gitignore" edit file page - And I see a commit error message - - @javascript - Scenario: I can create directory in repo - When I click on "New directory" link in repo - And I fill the new directory name - And I fill the commit message - And I fill the new branch name - And I click on "Create directory" - Then I am redirected to the new merge request page - - @javascript - Scenario: I can create directory in repo when I don't have write access - Given I don't have write access - When I click on "New directory" link in repo - Then I should see a notice about a new fork having been created - When I click on "New directory" link in repo - And I fill the new directory name - And I fill the commit message - And I click on "Create directory" - Then I am redirected to the fork's new merge request page - - @javascript - Scenario: I attempt to create an existing directory - When I click on "New directory" link in repo - And I fill an existing directory name - And I fill the commit message - And I click on "Create directory" - Then I see "Unable to create directory" - And I am redirected to the root directory - - @javascript - Scenario: I can see editing preview - Given I click on ".gitignore" file in repo - And I click button "Edit" - And I edit code - And I click link "Diff" - Then I see diff - - @javascript - Scenario: I can delete file and commit - Given I click on ".gitignore" file in repo - And I see the ".gitignore" - And I click on "Delete" - And I fill the commit message - And I click on "Delete file" - Then I am redirected to the files URL - And I don't see the ".gitignore" - - @javascript - Scenario: I can delete file and commit when I don't have write access - Given I don't have write access - And I click on ".gitignore" file in repo - And I see the ".gitignore" - And I click on "Delete" - Then I should see a Fork/Cancel combo - And I click button "Fork" - Then I should see a notice about a new fork having been created - When I click on "Delete" - And I fill the commit message - And I click on "Delete file" - Then I am redirected to the fork's new merge request page - And I can see the new commit message - - Scenario: I can browse directory with Browse Dir - Given I click on files directory - And I click on History link - Then I see Browse dir link - - Scenario: I can browse file with Browse File - Given I click on readme file - And I click on History link - Then I see Browse file link - - Scenario: I can browse code with Browse Code - Given I click on History link - Then I see Browse code link - - # Permalink - - Scenario: I click on the permalink link from a branch ref - Given I click on ".gitignore" file in repo - And I click on Permalink - Then I am redirected to the permalink URL - - Scenario: I don't see the permalink link from a SHA ref - Given I visit project source page for "6d394385cf567f80a8fd85055db1ab4c5295806f" - And I click on ".gitignore" file in repo - Then I don't see the permalink link - - @javascript - Scenario: I browse code with single quotes in the ref - Given I switch ref to 'test' - And I see the ref 'test' has been selected - And I visit the 'test' tree - Then I see the commit data - - @javascript - Scenario: I browse code with a leading dot in the directory - Given I switch ref to fix - And I visit the fix tree - Then I see the commit data for a directory with a leading dot - - Scenario: I browse LFS object - Given I click on "files/lfs/lfs_object.iso" file in repo - Then I should see download link and object size - And I should not see lfs pointer details - And I should see buttons for allowed commands - - @javascript - Scenario: I preview an SVG file - Given I click on "Upload file" link in repo - And I upload a new SVG file - And I fill the upload file commit message - And I fill the new branch name - And I click on "Upload file" - Given I visit the SVG file - Then I can see the new rendered SVG image diff --git a/spec/features/projects/user_browses_files_spec.rb b/spec/features/projects/user_browses_files_spec.rb new file mode 100644 index 00000000000..263a3a29a66 --- /dev/null +++ b/spec/features/projects/user_browses_files_spec.rb @@ -0,0 +1,188 @@ +require 'spec_helper' + +describe 'User browses files' do + include DropzoneHelper + + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project, name: 'Shop') } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:tree_path_ref_6d39438) { project_tree_path(project, '6d39438') } + let(:tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + context 'when browsing the master branch' do + before do + visit(tree_path_root_ref) + end + + it 'shows files from a repository' do + expect(page).to have_content('VERSION') + expect(page).to have_content('.gitignore') + expect(page).to have_content('LICENSE') + end + + it 'shows the "Browse Directory" link' do + click_link('files') + click_link('History') + + expect(page).to have_link('Browse Directory') + expect(page).not_to have_link('Browse Code') + end + + it 'shows the "Browse File" link' do + page.within('.tree-table') do + click_link('README.md') + end + click_link('History') + + expect(page).to have_link('Browse File') + expect(page).not_to have_link('Browse Files') + end + + it 'shows the "Browse Code" link' do + click_link('History') + + expect(page).to have_link('Browse Files') + expect(page).not_to have_link('Browse Directory') + end + + it 'redirects to the permalink URL' do + click_link('.gitignore') + click_link('Permalink') + + permalink_path = project_blob_path(project, "#{project.repository.commit.sha}/.gitignore") + + expect(current_path).to eq(permalink_path) + end + end + + context 'when browsing a specific ref' do + before do + visit(tree_path_ref_6d39438) + end + + it 'shows files from a repository for "6d39438"' do + expect(current_path).to eq(tree_path_ref_6d39438) + expect(page).to have_content('.gitignore') + expect(page).to have_content('LICENSE') + end + + it 'shows files from a repository with apostroph in its name', js: true do + first('.js-project-refs-dropdown').click + + page.within('.project-refs-form') do + click_link("'test'") + end + + expect(page).to have_selector('.dropdown-toggle-text', text: "'test'") + + visit(project_tree_path(project, "'test'")) + + expect(page).to have_css('.tree-commit-link', visible: true) + expect(page).not_to have_content('Loading commit data...') + end + + it 'shows the code with a leading dot in the directory', js: true do + first('.js-project-refs-dropdown').click + + page.within('.project-refs-form') do + click_link('fix') + end + + visit(project_tree_path(project, 'fix/.testdir')) + + expect(page).to have_css('.tree-commit-link', visible: true) + expect(page).not_to have_content('Loading commit data...') + end + + it 'does not show the permalink link' do + click_link('.gitignore') + + expect(page).not_to have_link('permalink') + end + end + + context 'when browsing a file content' do + before do + visit(tree_path_root_ref) + click_link('.gitignore') + end + + it 'shows a file content', js: true do + wait_for_requests + expect(page).to have_content('*.rbc') + end + end + + context 'when browsing a raw file' do + before do + visit(project_blob_path(project, File.join(RepoHelpers.sample_commit.id, RepoHelpers.sample_blob.path))) + end + + it 'shows a raw file content' do + click_link('Open raw') + expect(source).to eq('') # Body is filled in by gitlab-workhorse + end + end + + context 'when browsing an LFS object' do + before do + allow_any_instance_of(Project).to receive(:lfs_enabled?).and_return(true) + visit(project_tree_path(project, 'lfs')) + end + + it 'shows an LFS object' do + click_link('files') + click_link('lfs') + click_link('lfs_object.iso') + + expect(page).to have_content('Download (1.5 MB)') + expect(page).not_to have_content('version https://git-lfs.github.com/spec/v1') + expect(page).not_to have_content('oid sha256:91eff75a492a3ed0dfcb544d7f31326bc4014c8551849c192fd1e48d4dd2c897') + expect(page).not_to have_content('size 1575078') + + page.within('.content') do + expect(page).to have_content('Delete') + expect(page).to have_content('History') + expect(page).to have_content('Permalink') + expect(page).to have_content('Replace') + expect(page).not_to have_content('Annotate') + expect(page).not_to have_content('Blame') + expect(page).not_to have_content('Edit') + expect(page).to have_link('Download') + end + end + end + + context 'when previewing a file content' do + before do + visit(tree_path_root_ref) + end + + it 'shows a preview of a file content', js: true do + find('.add-to-tree').click + click_link('Upload file') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'New commit message') + end + + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Upload file') + + visit(project_blob_path(project, 'new_branch_name/logo_sample.svg')) + + expect(page).to have_css('.file-content img') + end + end +end diff --git a/spec/features/projects/user_create_dir_spec.rb b/spec/features/projects/user_create_dir_spec.rb deleted file mode 100644 index 5e302da8a63..00000000000 --- a/spec/features/projects/user_create_dir_spec.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'spec_helper' - -feature 'New directory creation', feature: true, js: true do - given(:user) { create(:user) } - given(:role) { :developer } - given(:project) { create(:project) } - - background do - sign_in(user) - project.team << [user, role] - visit project_tree_path(project, 'master') - open_new_directory_modal - fill_in 'dir_name', with: 'new_directory' - end - - def open_new_directory_modal - first('.add-to-tree').click - click_link 'New directory' - end - - def create_directory - click_button 'Create directory' - end - - context 'with default target branch' do - background do - create_directory - end - - scenario 'creates the directory in the default branch' do - expect(page).to have_content 'master' - expect(page).to have_content 'The directory has been successfully created' - expect(page).to have_content 'new_directory' - end - end - - context 'with a new target branch' do - given(:new_branch_name) { 'new-feature' } - - background do - fill_in :branch_name, with: new_branch_name - create_directory - end - - scenario 'creates the directory in the new branch' do - expect(page).to have_content new_branch_name - expect(page).to have_content 'The directory has been successfully created' - end - - scenario 'redirects to the merge request' do - expect(page).to have_content 'New Merge Request' - expect(page).to have_content "From #{new_branch_name} into master" - expect(page).to have_content 'Add new directory' - expect(current_path).to eq(project_new_merge_request_path(project)) - end - end -end diff --git a/spec/features/projects/user_creates_directory_spec.rb b/spec/features/projects/user_creates_directory_spec.rb new file mode 100644 index 00000000000..635bd4493dd --- /dev/null +++ b/spec/features/projects/user_creates_directory_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' + +feature 'User creates a directory', js: true do + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project) } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :developer] + sign_in(user) + visit project_tree_path(project, 'master') + end + + context 'with default target branch' do + before do + first('.add-to-tree').click + click_link('New directory') + end + + it 'creates the directory in the default branch' do + fill_in(:dir_name, with: 'new_directory') + click_button('Create directory') + + expect(page).to have_content('master') + expect(page).to have_content('The directory has been successfully created') + expect(page).to have_content('new_directory') + end + + it 'does not create a directory with a name of already existed directory' do + fill_in(:dir_name, with: 'files') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Create directory') + + expect(page).to have_content('A directory with this name already exists') + expect(current_path).to eq(project_tree_path(project, 'master')) + end + end + + context 'with a new target branch' do + before do + first('.add-to-tree').click + click_link('New directory') + fill_in(:dir_name, with: 'new_directory') + fill_in(:branch_name, with: 'new-feature') + click_button('Create directory') + end + + it 'creates the directory in the new branch and redirect to the merge request' do + expect(page).to have_content('new-feature') + expect(page).to have_content('The directory has been successfully created') + expect(page).to have_content('New Merge Request') + expect(page).to have_content('From new-feature into master') + expect(page).to have_content('Add new directory') + + expect(current_path).to eq(project_new_merge_request_path(project)) + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'creates a directory in a forked project' do + find('.add-to-tree').click + click_link('New directory') + + expect(page).to have_content(fork_message) + + find('.add-to-tree').click + click_link('New directory') + fill_in(:dir_name, with: 'new_directory') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Create directory') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + end + end +end diff --git a/spec/features/projects/user_creates_files_spec.rb b/spec/features/projects/user_creates_files_spec.rb new file mode 100644 index 00000000000..0c7f1a775c1 --- /dev/null +++ b/spec/features/projects/user_creates_files_spec.rb @@ -0,0 +1,153 @@ +require 'spec_helper' + +describe 'User creates files' do + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project, name: 'Shop') } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + context 'without commiting a new file' do + context 'when an user has write access' do + before do + visit(project_tree_path_root_ref) + end + + it 'opens new file page' do + find('.add-to-tree').click + click_link('New file') + + expect(page).to have_content('New file') + expect(page).to have_content('Commit message') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'opens new file page on a forked project' do + find('.add-to-tree').click + click_link('New file') + + expect(page).to have_selector('.file-editor') + expect(page).to have_content(fork_message) + expect(page).to have_content('New file') + expect(page).to have_content('Commit message') + end + end + end + + context 'with commiting a new file' do + context 'when an user has write access' do + before do + visit(project_tree_path_root_ref) + + find('.add-to-tree').click + click_link('New file') + end + + it 'creates and commit a new file', js: true do + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + new_file_path = project_blob_path(project, 'master/not_a_file.md') + + expect(current_path).to eq(new_file_path) + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + + it 'creates and commit a new file with new lines at the end of file', js: true do + execute_script('ace.edit("editor").setValue("Sample\n\n\n")') + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + new_file_path = project_blob_path(project, 'master/not_a_file.md') + + expect(current_path).to eq(new_file_path) + + find('.js-edit-blob').click + + expect(evaluate_script('ace.edit("editor").getValue()')).to eq("Sample\n\n\n") + end + + it 'creates and commit a new file with a directory name', js: true do + fill_in(:file_name, with: 'foo/bar/baz.txt') + + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_blob_path(project, 'master/foo/bar/baz.txt')) + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + + it 'creates and commit a new file specifying a new branch', js: true do + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_new_merge_request_path(project)) + + click_link('Changes') + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'creates and commit new file in forked project', js: true do + find('.add-to-tree').click + click_link('New file') + + expect(page).to have_selector('.file-editor') + + execute_script("ace.edit('editor').setValue('*.rbca')") + + fill_in(:file_name, with: 'not_a_file.md') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + expect(page).to have_content('New commit message') + end + end + end +end diff --git a/spec/features/projects/user_deletes_files_spec.rb b/spec/features/projects/user_deletes_files_spec.rb new file mode 100644 index 00000000000..97e60862b4f --- /dev/null +++ b/spec/features/projects/user_deletes_files_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' + +describe 'User deletes files' do + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project, name: 'Shop') } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + context 'when an user has write access' do + before do + project.team << [user, :master] + visit(project_tree_path_root_ref) + end + + it 'deletes the file', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Delete') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Delete file') + + expect(current_path).to eq(project_tree_path(project, 'master')) + expect(page).not_to have_content('.gitignore') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'deletes the file in a forked project', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Delete') + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + + expect(page).to have_content(fork_message) + + click_on('Delete') + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Delete file') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + expect(page).to have_content('New commit message') + end + end +end diff --git a/spec/features/projects/user_edits_files_spec.rb b/spec/features/projects/user_edits_files_spec.rb new file mode 100644 index 00000000000..eb26f1bc123 --- /dev/null +++ b/spec/features/projects/user_edits_files_spec.rb @@ -0,0 +1,122 @@ +require 'spec_helper' + +describe 'User edits files' do + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project, name: 'Shop') } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + context 'when an user has write access' do + before do + project.team << [user, :master] + visit(project_tree_path_root_ref) + end + + it 'inserts a content of a file', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + + expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca') + end + + it 'does not show the edit link if a file is binary' do + binary_file = File.join(project.repository.root_ref, 'files/images/logo-black.png') + visit(project_blob_path(project, binary_file)) + + expect(page).not_to have_link('edit') + end + + it 'commits an edited file', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_blob_path(project, 'master/.gitignore')) + + wait_for_requests + + expect(page).to have_content('*.rbca') + end + + it 'commits an edited file to a new branch', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Commit changes') + + expect(current_path).to eq(project_new_merge_request_path(project)) + + click_link('Changes') + + wait_for_requests + expect(page).to have_content('*.rbca') + end + + it 'shows the diff of an edited file', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + execute_script("ace.edit('editor').setValue('*.rbca')") + click_link('Preview changes') + + expect(page).to have_css('.line_holder.new') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'inserts a content of a file in a forked project', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + + expect(page).to have_content(fork_message) + + execute_script("ace.edit('editor').setValue('*.rbca')") + + expect(evaluate_script('ace.edit("editor").getValue()')).to eq('*.rbca') + end + + it 'commits an edited file in a forked project', js: true do + click_link('.gitignore') + find('.js-edit-blob').click + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + execute_script("ace.edit('editor').setValue('*.rbca')") + fill_in(:commit_message, with: 'New commit message', visible: true) + click_button('Commit changes') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + + wait_for_requests + + expect(page).to have_content('New commit message') + end + end +end diff --git a/spec/features/projects/user_replaces_files_spec.rb b/spec/features/projects/user_replaces_files_spec.rb new file mode 100644 index 00000000000..50f2ffc4bbf --- /dev/null +++ b/spec/features/projects/user_replaces_files_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' + +describe 'User replaces files' do + include DropzoneHelper + + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project, name: 'Shop') } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + sign_in(user) + end + + context 'when an user has write access' do + before do + project.team << [user, :master] + visit(project_tree_path_root_ref) + end + + it 'replaces an existed file with a new one', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Replace') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'Replacement file commit message') + end + + click_button('Replace file') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + expect(page).to have_content('Replacement file commit message') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'replaces an existed file with a new one in a forked project', js: true do + click_link('.gitignore') + + expect(page).to have_content('.gitignore') + + click_on('Replace') + + expect(page).to have_link('Fork') + expect(page).to have_button('Cancel') + + click_link('Fork') + + expect(page).to have_content(fork_message) + + click_on('Replace') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'Replacement file commit message') + end + + click_button('Replace file') + + expect(page).to have_content('Replacement file commit message') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + + click_link('Changes') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + end + end +end diff --git a/spec/features/projects/user_uploads_files_spec.rb b/spec/features/projects/user_uploads_files_spec.rb new file mode 100644 index 00000000000..64a1439badd --- /dev/null +++ b/spec/features/projects/user_uploads_files_spec.rb @@ -0,0 +1,82 @@ +require 'spec_helper' + +describe 'User uploads files' do + include DropzoneHelper + + let(:fork_message) do + "You're not allowed to make changes to this project directly. "\ + "A fork of this project has been created that you can make changes in, so you can submit a merge request." + end + let(:project) { create(:project, name: 'Shop') } + let(:project2) { create(:project, :repository, name: 'Another Project', path: 'another-project') } + let(:project_tree_path_root_ref) { project_tree_path(project, project.repository.root_ref) } + let(:project2_tree_path_root_ref) { project_tree_path(project2, project2.repository.root_ref) } + let(:user) { create(:user) } + + before do + project.team << [user, :master] + sign_in(user) + end + + context 'when an user has write access' do + before do + visit(project_tree_path_root_ref) + end + + it 'uploads and commit a new file', js: true do + find('.add-to-tree').click + click_link('Upload file') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'New commit message') + end + + fill_in(:branch_name, with: 'new_branch_name', visible: true) + click_button('Upload file') + + expect(page).to have_content('New commit message') + expect(current_path).to eq(project_new_merge_request_path(project)) + + click_link('Changes') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + end + end + + context 'when an user does not have write access' do + before do + project2.team << [user, :reporter] + visit(project2_tree_path_root_ref) + end + + it 'uploads and commit a new fileto a forked project', js: true do + find('.add-to-tree').click + click_link('Upload file') + + expect(page).to have_content(fork_message) + + find('.add-to-tree').click + click_link('Upload file') + drop_in_dropzone(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')) + + page.within('#modal-upload-blob') do + fill_in(:commit_message, with: 'New commit message') + end + + click_button('Upload file') + + expect(page).to have_content('New commit message') + + fork = user.fork_of(project2) + + expect(current_path).to eq(project_new_merge_request_path(fork)) + + click_link('Changes') + + expect(page).to have_content('Lorem ipsum dolor sit amet') + expect(page).to have_content('Sed ut perspiciatis unde omnis') + end + end +end diff --git a/spec/lib/gitlab/git/hook_spec.rb b/spec/lib/gitlab/git/hook_spec.rb index 73518656bde..19f45ea1cb2 100644 --- a/spec/lib/gitlab/git/hook_spec.rb +++ b/spec/lib/gitlab/git/hook_spec.rb @@ -2,6 +2,12 @@ require 'spec_helper' require 'fileutils' describe Gitlab::Git::Hook, lib: true do + before do + # We need this because in the spec/spec_helper.rb we define it like this: + # allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_call_original + end + describe "#trigger" do let(:project) { create(:project, :repository) } let(:repo_path) { project.repository.path } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dc0bdd9f4c7..3c142764e28 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -76,6 +76,11 @@ RSpec.configure do |config| TestEnv.cleanup end + config.before(:example) do + # Skip pre-receive hook check so we can use the web editor and merge. + allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) + end + config.before(:example, :request_store) do RequestStore.begin! end diff --git a/spec/support/dropzone_helper.rb b/spec/support/dropzone_helper.rb index 02fdeb08afe..fe72d320fcf 100644 --- a/spec/support/dropzone_helper.rb +++ b/spec/support/dropzone_helper.rb @@ -54,4 +54,23 @@ module DropzoneHelper loop until page.evaluate_script('window._dropzoneComplete === true') end end + + def drop_in_dropzone(file_path) + # Generate a fake input selector + page.execute_script <<-JS + var fakeFileInput = window.$('').attr( + {id: 'fakeFileInput', type: 'file'} + ).appendTo('body'); + JS + + # Attach the file to the fake input selector with Capybara + attach_file('fakeFileInput', file_path) + + # Add the file to a fileList array and trigger the fake drop event + page.execute_script <<-JS + var fileList = [$('#fakeFileInput')[0].files[0]]; + var e = jQuery.Event('drop', { dataTransfer : { files : fileList } }); + $('.dropzone')[0].dropzone.listeners[0].events.drop(e); + JS + end end From 4f47de62b47e136ffe335dc93acff3f6cd69b98f Mon Sep 17 00:00:00 2001 From: Nathan Neulinger Date: Mon, 10 Apr 2017 08:02:31 -0500 Subject: [PATCH 37/61] Stop sanitizing user 'name' when inserting into db Add spec tests for encoding --- app/models/user.rb | 2 +- .../unreleased/10085-stop-encoding-user-name.yml | 4 ++++ spec/models/user_spec.rb | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/10085-stop-encoding-user-name.yml diff --git a/app/models/user.rb b/app/models/user.rb index 4b01c2f19f0..2d39b1c1c34 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -699,7 +699,7 @@ class User < ActiveRecord::Base end def sanitize_attrs - %w[name username skype linkedin twitter].each do |attr| + %w[username skype linkedin twitter].each do |attr| value = public_send(attr) public_send("#{attr}=", Sanitize.clean(value)) if value.present? end diff --git a/changelogs/unreleased/10085-stop-encoding-user-name.yml b/changelogs/unreleased/10085-stop-encoding-user-name.yml new file mode 100644 index 00000000000..8fab474e047 --- /dev/null +++ b/changelogs/unreleased/10085-stop-encoding-user-name.yml @@ -0,0 +1,4 @@ +--- +title: "Insert user name directly without encoding" +merge_request: 10085 +author: Nathan Neulinger diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d04162a527f..c70f916a8bd 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1159,6 +1159,18 @@ describe User, models: true do end end + describe '#sanitize_attrs' do + let(:user) { build(:user, name: 'test & user', skype: 'test&user') } + + it 'encodes HTML entities in the Skype attribute' do + expect { user.sanitize_attrs }.to change { user.skype }.to('test&user') + end + + it 'does not encode HTML entities in the name attribute' do + expect { user.sanitize_attrs }.not_to change { user.name } + end + end + describe '#starred?' do it 'determines if user starred a project' do user = create :user From aaa78199c2408a05d81aa4ee3058e81bb732da16 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Wed, 12 Jul 2017 14:47:09 +0000 Subject: [PATCH 38/61] Update vue-resource --- app/assets/javascripts/blob/notebook/index.js | 3 +- .../javascripts/boards/boards_bundle.js | 6 +- .../boards/components/board_blank_state.js | 5 +- .../boards/components/modal/index.js | 6 +- app/assets/javascripts/boards/models/list.js | 13 +- .../boards/services/board_service.js | 5 - .../commit/pipelines/pipelines_table.vue | 10 +- .../diff_notes/components/resolve_btn.js | 22 ++-- .../diff_notes/services/resolve.js | 26 ++-- .../environments/mixins/environments_mixin.js | 18 ++- app/assets/javascripts/groups/index.js | 13 +- .../javascripts/issue_show/components/app.vue | 5 +- .../javascripts/jobs/job_details_mediator.js | 3 +- app/assets/javascripts/notes.js | 2 +- .../pipelines/components/pipelines.vue | 13 +- .../pipelines/components/stage.vue | 5 +- .../pipelines/pipeline_details_mediatior.js | 8 +- .../javascripts/sidebar/sidebar_mediator.js | 4 +- .../vue_shared/components/markdown/field.vue | 5 +- .../vue_shared/vue_resource_interceptor.js | 19 ++- .../unreleased/34534-update-vue-resource.yml | 4 + doc/development/fe_guide/vue.md | 121 ++++++++++++------ package.json | 2 +- .../environments/environment_spec.js | 9 ++ .../folder/environments_folder_view_spec.js | 4 + .../helpers/vue_resource_helper.js | 11 ++ .../issue_show/components/app_spec.js | 55 ++++---- yarn.lock | 102 ++++++++++++++- 28 files changed, 328 insertions(+), 171 deletions(-) create mode 100644 changelogs/unreleased/34534-update-vue-resource.yml create mode 100644 spec/javascripts/helpers/vue_resource_helper.js diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js index 36fe8a7184f..27312d718b0 100644 --- a/app/assets/javascripts/blob/notebook/index.js +++ b/app/assets/javascripts/blob/notebook/index.js @@ -51,8 +51,9 @@ export default () => { methods: { loadFile() { this.$http.get(el.dataset.endpoint) + .then(response => response.json()) .then((res) => { - this.json = res.json(); + this.json = res; this.loading = false; }) .catch((e) => { diff --git a/app/assets/javascripts/boards/boards_bundle.js b/app/assets/javascripts/boards/boards_bundle.js index b94009ee76b..88b054b76e6 100644 --- a/app/assets/javascripts/boards/boards_bundle.js +++ b/app/assets/javascripts/boards/boards_bundle.js @@ -81,8 +81,9 @@ $(() => { mounted () { Store.disabled = this.disabled; gl.boardService.all() + .then(response => response.json()) .then((resp) => { - resp.json().forEach((board) => { + resp.forEach((board) => { const list = Store.addList(board, this.defaultAvatar); if (list.type === 'closed') { @@ -97,7 +98,8 @@ $(() => { Store.addBlankState(); this.loading = false; - }).catch(() => new Flash('An error occurred. Please try again.')); + }) + .catch(() => new Flash('An error occurred. Please try again.')); }, methods: { updateTokens() { diff --git a/app/assets/javascripts/boards/components/board_blank_state.js b/app/assets/javascripts/boards/components/board_blank_state.js index 870e115bd1a..e7f16899362 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.js +++ b/app/assets/javascripts/boards/components/board_blank_state.js @@ -64,8 +64,9 @@ export default { // Save the labels gl.boardService.generateDefaultLists() - .then((resp) => { - resp.json().forEach((listObj) => { + .then(resp => resp.json()) + .then((data) => { + data.forEach((listObj) => { const list = Store.findList('title', listObj.title); list.id = listObj.id; diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js index 6356c266ee2..1d36519c75c 100644 --- a/app/assets/javascripts/boards/components/modal/index.js +++ b/app/assets/javascripts/boards/components/modal/index.js @@ -88,9 +88,9 @@ gl.issueBoards.IssuesModal = Vue.extend({ return gl.boardService.getBacklog(queryData(this.filter.path, { page: this.page, per: this.perPage, - })).then((res) => { - const data = res.json(); - + })) + .then(resp => resp.json()) + .then((data) => { if (clearIssues) { this.issues = []; } diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index b4b09b3876e..08f7c5ddcd2 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -40,9 +40,8 @@ class List { save () { return gl.boardService.createList(this.label.id) - .then((resp) => { - const data = resp.json(); - + .then(resp => resp.json()) + .then((data) => { this.id = data.id; this.type = data.list_type; this.position = data.position; @@ -91,8 +90,8 @@ class List { } return gl.boardService.getIssuesForList(this.id, data) - .then((resp) => { - const data = resp.json(); + .then(resp => resp.json()) + .then((data) => { this.loading = false; this.issuesSize = data.size; @@ -109,8 +108,8 @@ class List { this.issuesSize += 1; return gl.boardService.newIssue(this.id, issue) - .then((resp) => { - const data = resp.json(); + .then(resp => resp.json()) + .then((data) => { issue.id = data.iid; if (this.issuesSize > 1) { diff --git a/app/assets/javascripts/boards/services/board_service.js b/app/assets/javascripts/boards/services/board_service.js index db9bced2f89..3742507b236 100644 --- a/app/assets/javascripts/boards/services/board_service.js +++ b/app/assets/javascripts/boards/services/board_service.js @@ -23,11 +23,6 @@ class BoardService { url: bulkUpdatePath, }, }); - - Vue.http.interceptors.push((request, next) => { - request.headers['X-CSRF-Token'] = $.rails.csrfToken(); - next(); - }); } all () { diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue index 3c77f14d533..6d31b78b36d 100644 --- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue +++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue @@ -51,11 +51,11 @@ }, methods: { successCallback(resp) { - const response = resp.json(); - - // depending of the endpoint the response can either bring a `pipelines` key or not. - const pipelines = response.pipelines || response; - this.setCommonData(pipelines); + return resp.json().then((response) => { + // depending of the endpoint the response can either bring a `pipelines` key or not. + const pipelines = response.pipelines || response; + this.setCommonData(pipelines); + }); }, }, }; diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js b/app/assets/javascripts/diff_notes/components/resolve_btn.js index 9d51fb53eb2..efb6ced9f46 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_btn.js +++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, no-new, max-len */ +/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, max-len */ /* global CommentsStore */ /* global ResolveService */ /* global Flash */ @@ -64,8 +64,6 @@ const ResolveBtn = Vue.extend({ }); }, resolve: function () { - const errorFlashMsg = 'An error occurred when trying to resolve a comment. Please try again.'; - if (!this.canResolve) return; let promise; @@ -79,24 +77,20 @@ const ResolveBtn = Vue.extend({ .resolve(this.noteId); } - promise.then((response) => { - this.loading = false; + promise + .then(resp => resp.json()) + .then((data) => { + this.loading = false; - if (response.status === 200) { - const data = response.json(); const resolved_by = data ? data.resolved_by : null; CommentsStore.update(this.discussionId, this.noteId, !this.isResolved, resolved_by); this.discussion.updateHeadline(data); gl.mrWidget.checkStatus(); - } else { - new Flash(errorFlashMsg); - } - this.updateTooltip(); - }).catch(() => { - new Flash(errorFlashMsg); - }); + this.updateTooltip(); + }) + .catch(() => new Flash('An error occurred when trying to resolve a comment. Please try again.')); } }, mounted: function () { diff --git a/app/assets/javascripts/diff_notes/services/resolve.js b/app/assets/javascripts/diff_notes/services/resolve.js index 807ab11d292..2f063f6fe1f 100644 --- a/app/assets/javascripts/diff_notes/services/resolve.js +++ b/app/assets/javascripts/diff_notes/services/resolve.js @@ -1,4 +1,3 @@ -/* eslint-disable class-methods-use-this, one-var, camelcase, no-new, comma-dangle, no-param-reassign, max-len */ /* global Flash */ /* global CommentsStore */ @@ -32,27 +31,22 @@ class ResolveServiceClass { promise = this.resolveAll(mergeRequestId, discussionId); } - promise.then((response) => { - discussion.loading = false; - - if (response.status === 200) { - const data = response.json(); - const resolved_by = data ? data.resolved_by : null; + promise + .then(resp => resp.json()) + .then((data) => { + discussion.loading = false; + const resolvedBy = data ? data.resolved_by : null; if (isResolved) { discussion.unResolveAllNotes(); } else { - discussion.resolveAllNotes(resolved_by); + discussion.resolveAllNotes(resolvedBy); } gl.mrWidget.checkStatus(); discussion.updateHeadline(data); - } else { - throw new Error('An error occurred when trying to resolve discussion.'); - } - }).catch(() => { - new Flash('An error occurred when trying to resolve a discussion. Please try again.'); - }); + }) + .catch(() => new Flash('An error occurred when trying to resolve a discussion. Please try again.')); } resolveAll(mergeRequestId, discussionId) { @@ -62,7 +56,7 @@ class ResolveServiceClass { return this.discussionResource.save({ mergeRequestId, - discussionId + discussionId, }, {}); } @@ -73,7 +67,7 @@ class ResolveServiceClass { return this.discussionResource.delete({ mergeRequestId, - discussionId + discussionId, }, {}); } } diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index 25b24fbd6dc..8f4066e3a6e 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -1,17 +1,15 @@ export default { methods: { saveData(resp) { - const response = { - headers: resp.headers, - body: resp.json(), - }; + const headers = resp.headers; + return resp.json().then((response) => { + this.isLoading = false; - this.isLoading = false; - - this.store.storeAvailableCount(response.body.available_count); - this.store.storeStoppedCount(response.body.stopped_count); - this.store.storeEnvironments(response.body.environments); - this.store.setPagination(response.headers); + this.store.storeAvailableCount(response.available_count); + this.store.storeStoppedCount(response.stopped_count); + this.store.storeEnvironments(response.environments); + this.store.setPagination(headers); + }); }, }, }; diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js index ff601db2aa6..00e1bd94c9c 100644 --- a/app/assets/javascripts/groups/index.js +++ b/app/assets/javascripts/groups/index.js @@ -99,8 +99,10 @@ document.addEventListener('DOMContentLoaded', () => { page: currentPath, }, document.title, currentPath); - this.updateGroups(response.json()); - this.updatePagination(response.headers); + return response.json().then((data) => { + this.updateGroups(data); + this.updatePagination(response.headers); + }); }) .catch(this.handleErrorResponse); }, @@ -114,18 +116,19 @@ document.addEventListener('DOMContentLoaded', () => { }, leaveGroup(group, collection) { this.service.leaveGroup(group.leavePath) + .then(resp => resp.json()) .then((response) => { $.scrollTo(0); this.store.removeGroup(group, collection); // eslint-disable-next-line no-new - new Flash(response.json().notice, 'notice'); + new Flash(response.notice, 'notice'); }) - .catch((response) => { + .catch((error) => { let message = 'An error occurred. Please try again.'; - if (response.status === 403) { + if (error.status === 403) { message = 'Failed to leave the group. Please make sure you are not the only owner'; } diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue index 3d5fb7f441c..efae112923d 100644 --- a/app/assets/javascripts/issue_show/components/app.vue +++ b/app/assets/javascripts/issue_show/components/app.vue @@ -202,10 +202,7 @@ export default { this.poll = new Poll({ resource: this.service, method: 'getData', - successCallback: (res) => { - const data = res.json(); - this.store.updateState(data); - }, + successCallback: res => res.json().then(data => this.store.updateState(data)), errorCallback(err) { throw new Error(err); }, diff --git a/app/assets/javascripts/jobs/job_details_mediator.js b/app/assets/javascripts/jobs/job_details_mediator.js index 063c52fac74..cc014b815c4 100644 --- a/app/assets/javascripts/jobs/job_details_mediator.js +++ b/app/assets/javascripts/jobs/job_details_mediator.js @@ -54,9 +54,8 @@ export default class JobMediator { } successCallback(response) { - const data = response.json(); this.state.isLoading = false; - this.store.storeJob(data); + return response.json().then(data => this.store.storeJob(data)); } errorCallback() { diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 1a68c5bca00..b2c503d1656 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1270,7 +1270,7 @@ export default class Notes {
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue index 01ae07aad65..5df317a76bf 100644 --- a/app/assets/javascripts/pipelines/components/pipelines.vue +++ b/app/assets/javascripts/pipelines/components/pipelines.vue @@ -129,14 +129,11 @@ }, successCallback(resp) { - const response = { - headers: resp.headers, - body: resp.json(), - }; - - this.store.storeCount(response.body.count); - this.store.storePagination(response.headers); - this.setCommonData(response.body.pipelines); + return resp.json().then((response) => { + this.store.storeCount(response.count); + this.store.storePagination(resp.headers); + this.setCommonData(response.pipelines); + }); }, }, }; diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue index 87b2725a045..a4a27247406 100644 --- a/app/assets/javascripts/pipelines/components/stage.vue +++ b/app/assets/javascripts/pipelines/components/stage.vue @@ -73,8 +73,9 @@ export default { fetchJobs() { this.$http.get(this.stage.dropdown_path) - .then((response) => { - this.dropdownContent = response.json().html; + .then(response => response.json()) + .then((data) => { + this.dropdownContent = data.html; this.isLoading = false; }) .catch(() => { diff --git a/app/assets/javascripts/pipelines/pipeline_details_mediatior.js b/app/assets/javascripts/pipelines/pipeline_details_mediatior.js index 82537ea06f5..385e7430a7d 100644 --- a/app/assets/javascripts/pipelines/pipeline_details_mediatior.js +++ b/app/assets/javascripts/pipelines/pipeline_details_mediatior.js @@ -40,10 +40,10 @@ export default class pipelinesMediator { } successCallback(response) { - const data = response.json(); - - this.state.isLoading = false; - this.store.storePipeline(data); + return response.json().then((data) => { + this.state.isLoading = false; + this.store.storePipeline(data); + }); } errorCallback() { diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js index 5ccfb4ee9c1..721e92221cf 100644 --- a/app/assets/javascripts/sidebar/sidebar_mediator.js +++ b/app/assets/javascripts/sidebar/sidebar_mediator.js @@ -28,8 +28,8 @@ export default class SidebarMediator { fetch() { this.service.get() - .then((response) => { - const data = response.json(); + .then(response => response.json()) + .then((data) => { this.store.setAssigneeData(data); this.store.setTimeTrackingData(data); }) diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index 8303c556f64..4e10bbc7408 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -44,9 +44,8 @@ text: this.$slots.textarea[0].elm.value, }, ) - .then((res) => { - const data = res.json(); - + .then(resp => resp.json()) + .then((data) => { this.markdownPreviewLoading = false; this.markdownPreview = data.body; diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js index 740930dce5b..7f8e514fda1 100644 --- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js +++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js @@ -14,11 +14,22 @@ Vue.http.interceptors.push((request, next) => { }); }); -// Inject CSRF token so we don't break any tests. +// Inject CSRF token and parse headers. +// New Vue Resource version uses Headers, we are expecting a plain object to render pagination +// and polling. Vue.http.interceptors.push((request, next) => { if ($.rails) { - // eslint-disable-next-line no-param-reassign - request.headers['X-CSRF-Token'] = $.rails.csrfToken(); + request.headers.set('X-CSRF-Token', $.rails.csrfToken()); } - next(); + + next((response) => { + // Headers object has a `forEach` property that iterates through all values. + const headers = {}; + + response.headers.forEach((value, key) => { + headers[key] = value; + }); + // eslint-disable-next-line no-param-reassign + response.headers = headers; + }); }); diff --git a/changelogs/unreleased/34534-update-vue-resource.yml b/changelogs/unreleased/34534-update-vue-resource.yml new file mode 100644 index 00000000000..2d0af0c9bfe --- /dev/null +++ b/changelogs/unreleased/34534-update-vue-resource.yml @@ -0,0 +1,4 @@ +--- +title: Updates vue resource and code according to breaking changes +merge_request: +author: diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index a984bb6c94c..0742b202807 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -112,7 +112,50 @@ Vue Resource should only be imported in the service file. Vue.use(VueResource); ``` -### CSRF token +#### Vue-resource gotchas +#### Headers +Headers are being parsed into a plain object in an interceptor. +In Vue-resource 1.x `headers` object was changed into an `Headers` object. In order to not change all old code, an interceptor was added. + +If you need to write a unit test that takes the headers in consideration, you need to include an interceptor to parse the headers after your test interceptor. +You can see an example in `spec/javascripts/environments/environment_spec.js`: + ```javascript + import { headersInterceptor } from './helpers/vue_resource_helper'; + + beforeEach(() => { + Vue.http.interceptors.push(myInterceptor); + Vue.http.interceptors.push(headersInterceptor); + }); + + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, myInterceptor); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); + }); + ``` + +#### `.json()` +When making a request to the server, you will most likely need to access the body of the response. +Use `.json()` to convert. Because `.json()` returns a Promise the follwoing structure should be used: + + ```javascript + service.get('url') + .then(resp => resp.json()) + .then((data) => { + this.store.storeData(data); + }) + .catch(() => new Flash('Something went wrong')); + ``` + +When using `Poll` (`app/assets/javascripts/lib/utils/poll.js`), the `successCallback` needs to handle `.json()` as a Promise: + ```javascript + successCallback: (response) => { + return response.json().then((data) => { + // handle the response + }); + } + ``` + +#### CSRF token We use a Vue Resource interceptor to manage the CSRF token. `app/assets/javascripts/vue_shared/vue_resource_interceptor.js` holds all our common interceptors. Note: You don't need to load `app/assets/javascripts/vue_shared/vue_resource_interceptor.js` @@ -126,13 +169,13 @@ The following example shows an application: // store.js export default class Store { - /** + /** * This is where we will iniatialize the state of our data. * Usually in a small SPA you don't need any options when starting the store. In the case you do * need guarantee it's an Object and it's documented. - * - * @param {Object} options - */ + * + * @param {Object} options + */ constructor(options) { this.options = options; @@ -205,14 +248,14 @@ import Store from 'store'; import Service from 'service'; import TodoComponent from 'todoComponent'; export default { - /** + /** * Although most data belongs in the store, each component it's own state. * We want to show a loading spinner while we are fetching the todos, this state belong * in the component. * * We need to access the store methods through all methods of our component. * We need to access the state of our store. - */ + */ data() { const store = new Store(); @@ -396,42 +439,46 @@ need to test the rendered output. [Vue][vue-test] guide's to unit test show us e [Vue Resource Interceptors][vue-resource-interceptor] allow us to add a interceptor with the response we need: -```javascript - // Mock the service to return data - const interceptor = (request, next) => { - next(request.respondWith(JSON.stringify([{ - title: 'This is a todo', - body: 'This is the text' - }]), { - status: 200, - })); - }; + ```javascript + // Mock the service to return data + const interceptor = (request, next) => { + next(request.respondWith(JSON.stringify([{ + title: 'This is a todo', + body: 'This is the text' + }]), { + status: 200, + })); + }; - beforeEach(() => { - Vue.http.interceptors.push(interceptor); - }); + beforeEach(() => { + Vue.http.interceptors.push(interceptor); + }); - afterEach(() => { - Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); - }); + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); + }); - it('should do something', (done) => { - setTimeout(() => { - // Test received data - done(); - }, 0); - }); -``` + it('should do something', (done) => { + setTimeout(() => { + // Test received data + done(); + }, 0); + }); + ``` + +1. Headers interceptor +Refer to [this section](vue.md#headers) 1. Use `$.mount()` to mount the component -```javascript - // bad - new Component({ - el: document.createElement('div') - }); - // good - new Component().$mount(); +```javascript +// bad +new Component({ + el: document.createElement('div') +}); + +// good +new Component().$mount(); ``` [vue-docs]: http://vuejs.org/guide/index.html diff --git a/package.json b/package.json index 5a997e813f8..fd944531a6a 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "visibilityjs": "^1.2.4", "vue": "^2.2.6", "vue-loader": "^11.3.4", - "vue-resource": "^0.9.3", + "vue-resource": "^1.3.4", "vue-template-compiler": "^2.2.6", "webpack": "^2.6.1", "webpack-bundle-analyzer": "^2.8.2" diff --git a/spec/javascripts/environments/environment_spec.js b/spec/javascripts/environments/environment_spec.js index 6639a6b5e7b..0c8817a8148 100644 --- a/spec/javascripts/environments/environment_spec.js +++ b/spec/javascripts/environments/environment_spec.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import '~/flash'; import environmentsComponent from '~/environments/components/environment.vue'; import { environment, folder } from './mock_data'; +import { headersInterceptor } from '../helpers/vue_resource_helper'; describe('Environment', () => { preloadFixtures('static/environments/environments.html.raw'); @@ -25,12 +26,14 @@ describe('Environment', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsEmptyResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); }); afterEach(() => { Vue.http.interceptors = _.without( Vue.http.interceptors, environmentsEmptyResponseInterceptor, ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); }); it('should render the empty state', (done) => { @@ -54,6 +57,10 @@ describe('Environment', () => { describe('with paginated environments', () => { const environmentsResponseInterceptor = (request, next) => { + next((response) => { + response.headers.set('X-nExt-pAge', '2'); + }); + next(request.respondWith(JSON.stringify({ environments: [environment], stopped_count: 1, @@ -73,6 +80,7 @@ describe('Environment', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); component = new EnvironmentsComponent({ el: document.querySelector('#environments-list-view'), }); @@ -82,6 +90,7 @@ describe('Environment', () => { Vue.http.interceptors = _.without( Vue.http.interceptors, environmentsResponseInterceptor, ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); }); it('should render a table with environments', (done) => { diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js index 350078ad5f5..fdaea5c0b0c 100644 --- a/spec/javascripts/environments/folder/environments_folder_view_spec.js +++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import '~/flash'; import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue'; import { environmentsList } from '../mock_data'; +import { headersInterceptor } from '../../helpers/vue_resource_helper'; describe('Environments Folder View', () => { preloadFixtures('static/environments/environments_folder_view.html.raw'); @@ -36,6 +37,8 @@ describe('Environments Folder View', () => { beforeEach(() => { Vue.http.interceptors.push(environmentsResponseInterceptor); + Vue.http.interceptors.push(headersInterceptor); + component = new EnvironmentsFolderViewComponent({ el: document.querySelector('#environments-folder-list-view'), }); @@ -45,6 +48,7 @@ describe('Environments Folder View', () => { Vue.http.interceptors = _.without( Vue.http.interceptors, environmentsResponseInterceptor, ); + Vue.http.interceptors = _.without(Vue.http.interceptors, headersInterceptor); }); it('should render a table with environments', (done) => { diff --git a/spec/javascripts/helpers/vue_resource_helper.js b/spec/javascripts/helpers/vue_resource_helper.js new file mode 100644 index 00000000000..0d1bf5e2e80 --- /dev/null +++ b/spec/javascripts/helpers/vue_resource_helper.js @@ -0,0 +1,11 @@ +// eslint-disable-next-line import/prefer-default-export +export const headersInterceptor = (request, next) => { + next((response) => { + const headers = {}; + response.headers.forEach((value, key) => { + headers[key] = value; + }); + // eslint-disable-next-line no-param-reassign + response.headers = headers; + }); +}; diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js index bc13373a27e..81ce18bf2fb 100644 --- a/spec/javascripts/issue_show/components/app_spec.js +++ b/spec/javascripts/issue_show/components/app_spec.js @@ -3,7 +3,6 @@ import '~/render_math'; import '~/render_gfm'; import issuableApp from '~/issue_show/components/app.vue'; import eventHub from '~/issue_show/event_hub'; -import Poll from '~/lib/utils/poll'; import issueShowData from '../mock_data'; function formatText(text) { @@ -11,16 +10,26 @@ function formatText(text) { } describe('Issuable output', () => { + let requestData = issueShowData.initialRequest; + document.body.innerHTML = ''; + const interceptor = (request, next) => { + next(request.respondWith(JSON.stringify(requestData), { + status: 200, + })); + }; + let vm; - beforeEach(() => { + beforeEach((done) => { spyOn(eventHub, '$emit'); - spyOn(Poll.prototype, 'makeRequest'); const IssuableDescriptionComponent = Vue.extend(issuableApp); + requestData = issueShowData.initialRequest; + Vue.http.interceptors.push(interceptor); + vm = new IssuableDescriptionComponent({ propsData: { canUpdate: true, @@ -40,15 +49,17 @@ describe('Issuable output', () => { projectPath: '/', }, }).$mount(); + + setTimeout(done); + }); + + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor); + + vm.poll.stop(); }); it('should render a title/description/edited and update title/description/edited on update', (done) => { - vm.poll.options.successCallback({ - json() { - return issueShowData.initialRequest; - }, - }); - let editedText; Vue.nextTick() .then(() => { @@ -64,13 +75,10 @@ describe('Issuable output', () => { expect(editedText.querySelector('time')).toBeTruthy(); }) .then(() => { - vm.poll.options.successCallback({ - json() { - return issueShowData.secondRequest; - }, - }); + requestData = issueShowData.secondRequest; + vm.poll.makeRequest(); }) - .then(Vue.nextTick) + .then(() => new Promise(resolve => setTimeout(resolve))) .then(() => { expect(document.querySelector('title').innerText).toContain('2 (#1)'); expect(vm.$el.querySelector('.title').innerHTML).toContain('

2

'); @@ -304,7 +312,7 @@ describe('Issuable output', () => { it('stops polling when deleting', (done) => { spyOn(gl.utils, 'visitUrl'); - spyOn(vm.poll, 'stop'); + spyOn(vm.poll, 'stop').and.callThrough(); spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => { resolve({ json() { @@ -347,23 +355,14 @@ describe('Issuable output', () => { describe('open form', () => { it('shows locked warning if form is open & data is different', (done) => { - vm.poll.options.successCallback({ - json() { - return issueShowData.initialRequest; - }, - }); - Vue.nextTick() .then(() => { vm.openForm(); - vm.poll.options.successCallback({ - json() { - return issueShowData.secondRequest; - }, - }); + requestData = issueShowData.secondRequest; + vm.poll.makeRequest(); }) - .then(Vue.nextTick) + .then(() => new Promise(resolve => setTimeout(resolve))) .then(() => { expect( vm.formState.lockedWarningVisible, diff --git a/yarn.lock b/yarn.lock index b04eebe60af..98da6a984d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1575,6 +1575,12 @@ deckar01-task_list@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deckar01-task_list/-/deckar01-task_list-2.0.0.tgz#7f7a595430d21b3036ed5dfbf97d6b65de18e2c9" +decompress-response@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + dependencies: + mimic-response "^1.0.0" + deep-extend@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" @@ -1712,6 +1718,10 @@ dropzone@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-4.2.0.tgz#fbe7acbb9918e0706489072ef663effeef8a79f3" +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + duplexer@^0.1.1, duplexer@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" @@ -2445,6 +2455,10 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + getpass@^0.1.1: version "0.1.6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" @@ -2521,6 +2535,25 @@ got@^3.2.0: read-all-stream "^3.0.0" timed-out "^2.0.0" +got@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + graceful-fs@^4.1.11, graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2578,6 +2611,16 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-symbol-support-x@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.3.0.tgz#588bd6927eaa0e296afae24160659167fc2be4f8" + +has-to-string-tag-x@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.3.0.tgz#78e3d98c3c0ec9413e970eb8d766249a1e13058f" + dependencies: + has-symbol-support-x "^1.3.0" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -2902,6 +2945,10 @@ is-number@^2.0.2, is-number@^2.1.0: dependencies: kind-of "^3.0.2" +is-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -2918,7 +2965,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -2950,6 +2997,10 @@ is-resolvable@^1.0.0: dependencies: tryit "^1.0.1" +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + is-stream@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3087,6 +3138,13 @@ istanbul@^0.4.5: which "^1.1.1" wordwrap "^1.0.0" +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + jasmine-core@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.3.tgz#45072950e4a42b1e322fe55c001100a465d77815" @@ -3633,6 +3691,10 @@ mime@1.3.4, mime@1.3.x, mime@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" +mimic-response@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" + minimalistic-assert@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" @@ -3981,6 +4043,14 @@ osenv@^0.1.0: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + p-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" @@ -3991,6 +4061,12 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" +p-timeout@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.0.tgz#9820f99434c5817868b4f34809ee5291660d5b6c" + dependencies: + p-finally "^1.0.0" + package-json@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/package-json/-/package-json-1.2.0.tgz#c8ecac094227cdf76a316874ed05e27cc939a0e0" @@ -4419,7 +4495,7 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -prepend-http@^1.0.0: +prepend-http@^1.0.0, prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -5384,6 +5460,10 @@ timed-out@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + timers-browserify@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" @@ -5545,6 +5625,12 @@ url-loader@^0.5.8: loader-utils "^1.0.2" mime "1.3.x" +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + url-parse@1.0.x: version "1.0.5" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b" @@ -5559,6 +5645,10 @@ url-parse@^1.0.1, url-parse@^1.1.1: querystringify "0.0.x" requires-port "1.0.x" +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" @@ -5657,9 +5747,11 @@ vue-loader@^11.3.4: vue-style-loader "^2.0.0" vue-template-es2015-compiler "^1.2.2" -vue-resource@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-0.9.3.tgz#ab46e1c44ea219142dcc28ae4043b3b04c80959d" +vue-resource@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.3.4.tgz#9fc0bdf6a2f5cab430129fc99d347b3deae7b099" + dependencies: + got "^7.0.0" vue-style-loader@^2.0.0: version "2.0.5" From 2baef3951c7c94b0347150390a253464c8eb4b8e Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Wed, 12 Jul 2017 23:47:54 +0900 Subject: [PATCH 39/61] Enable BangFormat in scss-lint --- .scss-lint.yml | 2 +- app/assets/stylesheets/framework/dropdowns.scss | 4 ++-- app/assets/stylesheets/framework/header.scss | 2 +- app/assets/stylesheets/pages/boards.scss | 6 +++--- app/assets/stylesheets/pages/pipeline_schedules.scss | 2 +- app/assets/stylesheets/print.scss | 2 +- changelogs/unreleased/enable-scss-lint-bang-format.yml | 4 ++++ 7 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 changelogs/unreleased/enable-scss-lint-bang-format.yml diff --git a/.scss-lint.yml b/.scss-lint.yml index db234ad739c..acf04bf0735 100644 --- a/.scss-lint.yml +++ b/.scss-lint.yml @@ -10,7 +10,7 @@ linters: # Reports when you use improper spacing around ! (the "bang") in !default, # !global, !important, and !optional flags. BangFormat: - enabled: false + enabled: true # Whether or not to prefer `border: 0` over `border: none`. BorderZero: diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index dc4ed42544f..b6b4fc98656 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -675,8 +675,8 @@ } .pika-single { - position: relative!important; - top: 0!important; + position: relative !important; + top: 0 !important; border: 0; box-shadow: none; } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 5bd6c095109..20fb10c28d4 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -330,7 +330,7 @@ header { padding-left: 5px; .nav > li:not(.hidden-xs) { - display: table-cell!important; + display: table-cell !important; width: 25%; a { diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 85109fec91a..df858cffe09 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -11,7 +11,7 @@ .is-dragging { // Important because plugin sets inline CSS - opacity: 1!important; + opacity: 1 !important; * { -webkit-user-select: none; @@ -19,8 +19,8 @@ -ms-user-select: none; user-select: none; // !important to make sure no style can override this when dragging - cursor: -webkit-grabbing!important; - cursor: grabbing!important; + cursor: -webkit-grabbing !important; + cursor: grabbing !important; } } diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss index dc719a6ba94..7f893bcf68b 100644 --- a/app/assets/stylesheets/pages/pipeline_schedules.scss +++ b/app/assets/stylesheets/pages/pipeline_schedules.scss @@ -1,7 +1,7 @@ .js-pipeline-schedule-form { .dropdown-select, .dropdown-menu-toggle { - width: 100%!important; + width: 100% !important; } .gl-field-error { diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss index 136d0c79467..113e6e86bb5 100644 --- a/app/assets/stylesheets/print.scss +++ b/app/assets/stylesheets/print.scss @@ -37,7 +37,7 @@ ul.notes-form, .issuable-details .content-block-small, .edit-link, .note-action-button { - display: none!important; + display: none !important; } pre { diff --git a/changelogs/unreleased/enable-scss-lint-bang-format.yml b/changelogs/unreleased/enable-scss-lint-bang-format.yml new file mode 100644 index 00000000000..0b73760198e --- /dev/null +++ b/changelogs/unreleased/enable-scss-lint-bang-format.yml @@ -0,0 +1,4 @@ +--- +title: Enable BangFormat in scss-lint [ci skip] +merge_request: 12815 +author: Takuya Noguchi From 531157f5b4e35393cb1952365a534dbab6252950 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 12 Jul 2017 10:02:53 -0500 Subject: [PATCH 40/61] Fix spec name grammer --- spec/presenters/merge_request_presenter_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index ca6c67a6235..c1a0313b13c 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -332,7 +332,7 @@ describe MergeRequestPresenter do end end - context 'when target branch does not exists' do + context 'when target branch does not exist' do it 'returns nil' do allow(resource).to receive(:target_branch_exists?) { false } @@ -356,7 +356,7 @@ describe MergeRequestPresenter do end end - context 'when target branch does not exists' do + context 'when target branch does not exist' do it 'returns nil' do allow(resource).to receive(:target_branch_exists?) { false } @@ -379,7 +379,7 @@ describe MergeRequestPresenter do end end - context 'when source branch does not exists' do + context 'when source branch does not exist' do it 'returns nil' do allow(resource).to receive(:source_branch_exists?) { false } From 47c844bf34cff269c4c31c2327f1684f5265ebd4 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 12 Jul 2017 16:31:36 +0200 Subject: [PATCH 41/61] Add Gitaly notes and annotations to Gitlab::Git --- lib/gitlab/git/attributes.rb | 5 +++++ lib/gitlab/git/blame.rb | 3 +++ lib/gitlab/git/blob.rb | 4 ++++ lib/gitlab/git/blob_snippet.rb | 2 ++ lib/gitlab/git/branch.rb | 2 ++ lib/gitlab/git/commit.rb | 4 ++++ lib/gitlab/git/commit_stats.rb | 4 ++++ lib/gitlab/git/compare.rb | 2 ++ lib/gitlab/git/diff_collection.rb | 2 ++ lib/gitlab/git/env.rb | 2 ++ lib/gitlab/git/gitmodules_parser.rb | 2 ++ lib/gitlab/git/hook.rb | 4 ++++ lib/gitlab/git/index.rb | 4 ++++ lib/gitlab/git/path_helper.rb | 2 ++ lib/gitlab/git/popen.rb | 2 ++ lib/gitlab/git/ref.rb | 3 +++ lib/gitlab/git/repository.rb | 5 +++++ lib/gitlab/git/rev_list.rb | 4 ++++ lib/gitlab/git/tag.rb | 2 ++ lib/gitlab/git/tree.rb | 6 ++++++ lib/gitlab/git/util.rb | 2 ++ 21 files changed, 66 insertions(+) diff --git a/lib/gitlab/git/attributes.rb b/lib/gitlab/git/attributes.rb index 42140ecc993..2d20cd473a7 100644 --- a/lib/gitlab/git/attributes.rb +++ b/lib/gitlab/git/attributes.rb @@ -1,3 +1,8 @@ +# Gitaly note: JV: not sure what to make of this class. Why does it use +# the full disk path of the repository to look up attributes This is +# problematic in Gitaly, because Gitaly hides the full disk path to the +# repository from gitlab-ce. + module Gitlab module Git # Class for parsing Git attribute files and extracting the attributes for diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb index 66829a03c2e..0deaab01b5b 100644 --- a/lib/gitlab/git/blame.rb +++ b/lib/gitlab/git/blame.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: needs 1 RPC for #load_blame. + module Gitlab module Git class Blame @@ -24,6 +26,7 @@ module Gitlab private + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/376 def load_blame cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{@repo.path} blame -p #{@sha} -- #{@path}) # Read in binary mode to ensure ASCII-8BIT diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index ea386c2ddcb..b6dd3cd20e0 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: seems to be completely migrated (behind feature flags). + module Gitlab module Git class Blob @@ -107,6 +109,8 @@ module Gitlab detect && detect[:type] == :binary end + private + # Recursive search of blob id by path # # Ex. diff --git a/lib/gitlab/git/blob_snippet.rb b/lib/gitlab/git/blob_snippet.rb index d7975f88aaa..68116e775c6 100644 --- a/lib/gitlab/git/blob_snippet.rb +++ b/lib/gitlab/git/blob_snippet.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git class BlobSnippet diff --git a/lib/gitlab/git/branch.rb b/lib/gitlab/git/branch.rb index 124526e4b59..e2be9d784b9 100644 --- a/lib/gitlab/git/branch.rb +++ b/lib/gitlab/git/branch.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git class Branch < Ref diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index 9c0606d780a..8ab3b0498ff 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -48,6 +48,7 @@ module Gitlab # # Commit.find(repo, 'master') # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/321 def find(repo, commit_id = "HEAD") return commit_id if commit_id.is_a?(Gitlab::Git::Commit) return decorate(commit_id) if commit_id.is_a?(Rugged::Commit) @@ -124,6 +125,7 @@ module Gitlab # are documented here: # http://www.rubydoc.info/github/libgit2/rugged/Rugged#SORT_NONE-constant) # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/326 def find_all(repo, options = {}) actual_options = options.dup @@ -243,6 +245,8 @@ module Gitlab # Shows the diff between the commit's parent and the commit. # # Cuts out the header and stats from #to_patch and returns only the diff. + # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/324 def to_diff diff_from_parent.patch end diff --git a/lib/gitlab/git/commit_stats.rb b/lib/gitlab/git/commit_stats.rb index e9118bbed0e..57c29ad112c 100644 --- a/lib/gitlab/git/commit_stats.rb +++ b/lib/gitlab/git/commit_stats.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: 1 RPC, migration in progress. + # Gitlab::Git::CommitStats counts the additions, deletions, and total changes # in a commit. module Gitlab @@ -6,6 +8,8 @@ module Gitlab attr_reader :id, :additions, :deletions, :total # Instantiate a CommitStats object + # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/323 def initialize(commit) @id = commit.id @additions = 0 diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb index 78e440395a5..7cb842256d0 100644 --- a/lib/gitlab/git/compare.rb +++ b/lib/gitlab/git/compare.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git class Compare diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index 555894907cc..0d8fe185ac5 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git class DiffCollection diff --git a/lib/gitlab/git/env.rb b/lib/gitlab/git/env.rb index 0fdc57ec954..f80193ac553 100644 --- a/lib/gitlab/git/env.rb +++ b/lib/gitlab/git/env.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git # Ephemeral (per request) storage for environment variables that some Git diff --git a/lib/gitlab/git/gitmodules_parser.rb b/lib/gitlab/git/gitmodules_parser.rb index f4e3b5e5129..4a43b9b444d 100644 --- a/lib/gitlab/git/gitmodules_parser.rb +++ b/lib/gitlab/git/gitmodules_parser.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git class GitmodulesParser diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb index 5042916343b..8f0c377ef4f 100644 --- a/lib/gitlab/git/hook.rb +++ b/lib/gitlab/git/hook.rb @@ -1,3 +1,7 @@ +# Gitaly note: JV: looks like this is only used by GitHooksService in +# app/services. We shouldn't bother migrating this until we know how +# GitHooksService will be migrated. + module Gitlab module Git class Hook diff --git a/lib/gitlab/git/index.rb b/lib/gitlab/git/index.rb index 666743006e5..db532600d1b 100644 --- a/lib/gitlab/git/index.rb +++ b/lib/gitlab/git/index.rb @@ -1,3 +1,7 @@ +# Gitaly note: JV: When the time comes I think we will want to copy this +# class into Gitaly. None of its methods look like they should be RPC's. +# The RPC's will be at a higher level. + module Gitlab module Git class Index diff --git a/lib/gitlab/git/path_helper.rb b/lib/gitlab/git/path_helper.rb index 0148cd8df05..42c80aabd0a 100644 --- a/lib/gitlab/git/path_helper.rb +++ b/lib/gitlab/git/path_helper.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git class PathHelper diff --git a/lib/gitlab/git/popen.rb b/lib/gitlab/git/popen.rb index df9ca3ee5ac..25fa62ce4bd 100644 --- a/lib/gitlab/git/popen.rb +++ b/lib/gitlab/git/popen.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + require 'open3' module Gitlab diff --git a/lib/gitlab/git/ref.rb b/lib/gitlab/git/ref.rb index ebf7393dc61..c1a10688285 100644 --- a/lib/gitlab/git/ref.rb +++ b/lib/gitlab/git/ref.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: probably no RPC's here (just one interaction with Rugged). + module Gitlab module Git class Ref @@ -24,6 +26,7 @@ module Gitlab str.gsub(/\Arefs\/heads\//, '') end + # Gitaly: this method will probably be migrated indirectly via its call sites. def self.dereference_object(object) object = object.target while object.is_a?(Rugged::Tag::Annotation) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index e51966313d4..b79e28cb150 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -553,6 +553,7 @@ module Gitlab # @repository.submodule_url_for('master', 'rack') # # => git@localhost:rack.git # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/329 def submodule_url_for(ref, path) Gitlab::GitalyClient.migrate(:submodule_url_for) do |is_enabled| if is_enabled @@ -567,6 +568,8 @@ module Gitlab end # Return total commits count accessible from passed ref + # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/330 def commit_count(ref) gitaly_migrate(:commit_count) do |is_enabled| if is_enabled @@ -838,6 +841,7 @@ module Gitlab # Ex. # repo.ls_files('master') # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/327 def ls_files(ref) actual_ref = ref || root_ref @@ -864,6 +868,7 @@ module Gitlab raw_output.compact end + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/328 def copy_gitattributes(ref) begin commit = lookup(ref) diff --git a/lib/gitlab/git/rev_list.rb b/lib/gitlab/git/rev_list.rb index a16b0ed76f4..2b5785a1f08 100644 --- a/lib/gitlab/git/rev_list.rb +++ b/lib/gitlab/git/rev_list.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: will probably be migrated indirectly by migrating the call sites. + module Gitlab module Git class RevList @@ -15,6 +17,8 @@ module Gitlab end # This methods returns an array of missed references + # + # Should become obsolete after https://gitlab.com/gitlab-org/gitaly/issues/348. def missed_ref execute([*base_args, '--max-count=1', oldrev, "^#{newrev}"]) end diff --git a/lib/gitlab/git/tag.rb b/lib/gitlab/git/tag.rb index b5342c3d310..9a39de6ad07 100644 --- a/lib/gitlab/git/tag.rb +++ b/lib/gitlab/git/tag.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. +# module Gitlab module Git class Tag < Ref diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb index b6d4e6cfe46..8122ff0e81f 100644 --- a/lib/gitlab/git/tree.rb +++ b/lib/gitlab/git/tree.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: needs 1 RPC, migration is in progress. + module Gitlab module Git class Tree @@ -10,6 +12,8 @@ module Gitlab # Get list of tree objects # for repository based on commit sha and path # Uses rugged for raw objects + # + # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/320 def where(repository, sha, path = nil) path = nil if path == '' || path == '/' @@ -40,6 +44,8 @@ module Gitlab end end + private + # Recursive search of tree id for path # # Ex. diff --git a/lib/gitlab/git/util.rb b/lib/gitlab/git/util.rb index 7973da2e8f8..4708f22dcb3 100644 --- a/lib/gitlab/git/util.rb +++ b/lib/gitlab/git/util.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: no RPC's here. + module Gitlab module Git module Util From 1e7e927e587c2eb419e1118900c4a5f7a62621af Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Tue, 11 Jul 2017 10:31:11 -0700 Subject: [PATCH 42/61] Fix wording of nav toggle --- app/views/layouts/header/_default.html.haml | 2 +- app/views/layouts/header/_new.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index ed44263741e..25acdb700ef 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -75,7 +75,7 @@ %li = link_to "Settings", profile_path %li - = link_to "Turn on new nav", profile_preferences_path(anchor: "new-navigation") + = link_to "Turn on new navigation", profile_preferences_path(anchor: "new-navigation") %li.divider %li = link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link" diff --git a/app/views/layouts/header/_new.html.haml b/app/views/layouts/header/_new.html.haml index bee7291da45..5bc15d68631 100644 --- a/app/views/layouts/header/_new.html.haml +++ b/app/views/layouts/header/_new.html.haml @@ -69,7 +69,7 @@ %li = link_to "Settings", profile_path %li - = link_to "Turn off new nav", profile_preferences_path(anchor: "new-navigation") + = link_to "Turn off new navigation", profile_preferences_path(anchor: "new-navigation") %li.divider %li = link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link" From c718d7fa08d7354ed9e0fd33e7b506e8a58ae224 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 12 Jul 2017 16:47:52 +0100 Subject: [PATCH 43/61] Update gitlab-shell to v5.3.1 This fixes an issue where the merge request URLs for a push returned an error, which made gitlab-shell show a stacktrace to the user. --- GITLAB_SHELL_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index e230c8396d1..c7cb1311a64 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -5.3.0 \ No newline at end of file +5.3.1 From a2030dc1ff9896dd384aedfaf0cb441e88551ca3 Mon Sep 17 00:00:00 2001 From: Sid Sijbrandij Date: Wed, 12 Jul 2017 15:56:36 +0000 Subject: [PATCH 44/61] Deep link --- doc/install/requirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/install/requirements.md b/doc/install/requirements.md index a3d676433e6..141df55f6bc 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -69,7 +69,7 @@ so keep in mind that you need at least 4GB available before running GitLab. With less memory GitLab will give strange errors during the reconfigure run and 500 errors during usage. -- 1GB RAM + 3GB of swap is the absolute minimum but we strongly **advise against** this amount of memory. See the unicorn worker section below for more advice. +- 1GB RAM + 3GB of swap is the absolute minimum but we strongly **advise against** this amount of memory. See the [unicorn worker section below](#unicorn-workers) for more advice. - 2GB RAM + 2GB swap supports up to 100 users but it will be very slow - **4GB RAM** is the **recommended** memory size for all installations and supports up to 100 users - 8GB RAM supports up to 1,000 users From 0b0e89ef7b5708cb2ac488d4641e071ce842ca23 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 12 Jul 2017 17:06:35 +0200 Subject: [PATCH 45/61] Try to eliminate unused diff options --- lib/gitlab/git/diff.rb | 100 ++----------------------------- spec/lib/gitlab/git/diff_spec.rb | 10 ++-- 2 files changed, 9 insertions(+), 101 deletions(-) diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index cf7829a583b..cf95f673667 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -1,3 +1,5 @@ +# Gitaly note: JV: needs RPC for Gitlab::Git::Diff.between. + # Gitlab::Git::Diff is a wrapper around native Rugged::Diff object module Gitlab module Git @@ -81,110 +83,16 @@ module Gitlab # Return a copy of the +options+ hash containing only keys that can be # passed to Rugged. Allowed options are: # - # :max_size :: - # An integer specifying the maximum byte size of a file before a it - # will be treated as binary. The default value is 512MB. - # - # :context_lines :: - # The number of unchanged lines that define the boundary of a hunk - # (and to display before and after the actual changes). The default is - # 3. - # - # :interhunk_lines :: - # The maximum number of unchanged lines between hunk boundaries before - # the hunks will be merged into a one. The default is 0. - # - # :old_prefix :: - # The virtual "directory" to prefix to old filenames in hunk headers. - # The default is "a". - # - # :new_prefix :: - # The virtual "directory" to prefix to new filenames in hunk headers. - # The default is "b". - # - # :reverse :: - # If true, the sides of the diff will be reversed. - # - # :force_text :: - # If true, all files will be treated as text, disabling binary - # attributes & detection. - # - # :ignore_whitespace :: - # If true, all whitespace will be ignored. - # # :ignore_whitespace_change :: # If true, changes in amount of whitespace will be ignored. # - # :ignore_whitespace_eol :: - # If true, whitespace at end of line will be ignored. - # - # :ignore_submodules :: - # if true, submodules will be excluded from the diff completely. - # - # :patience :: - # If true, the "patience diff" algorithm will be used (currenlty - # unimplemented). - # - # :include_ignored :: - # If true, ignored files will be included in the diff. - # - # :include_untracked :: - # If true, untracked files will be included in the diff. - # - # :include_unmodified :: - # If true, unmodified files will be included in the diff. - # - # :recurse_untracked_dirs :: - # Even if +:include_untracked+ is true, untracked directories will - # only be marked with a single entry in the diff. If this flag is set - # to true, all files under ignored directories will be included in the - # diff, too. - # # :disable_pathspec_match :: # If true, the given +*paths+ will be applied as exact matches, # instead of as fnmatch patterns. # - # :deltas_are_icase :: - # If true, filename comparisons will be made with case-insensitivity. - # - # :include_untracked_content :: - # if true, untracked content will be contained in the the diff patch - # text. - # - # :skip_binary_check :: - # If true, diff deltas will be generated without spending time on - # binary detection. This is useful to improve performance in cases - # where the actual file content difference is not needed. - # - # :include_typechange :: - # If true, type changes for files will not be interpreted as deletion - # of the "old file" and addition of the "new file", but will generate - # typechange records. - # - # :include_typechange_trees :: - # Even if +:include_typechange+ is true, blob -> tree changes will - # still usually be handled as a deletion of the blob. If this flag is - # set to true, blob -> tree changes will be marked as typechanges. - # - # :ignore_filemode :: - # If true, file mode changes will be ignored. - # - # :recurse_ignored_dirs :: - # Even if +:include_ignored+ is true, ignored directories will only be - # marked with a single entry in the diff. If this flag is set to true, - # all files under ignored directories will be included in the diff, - # too. def filter_diff_options(options, default_options = {}) - allowed_options = [:max_size, :context_lines, :interhunk_lines, - :old_prefix, :new_prefix, :reverse, :force_text, - :ignore_whitespace, :ignore_whitespace_change, - :ignore_whitespace_eol, :ignore_submodules, - :patience, :include_ignored, :include_untracked, - :include_unmodified, :recurse_untracked_dirs, - :disable_pathspec_match, :deltas_are_icase, - :include_untracked_content, :skip_binary_check, - :include_typechange, :include_typechange_trees, - :ignore_filemode, :recurse_ignored_dirs, :paths, + allowed_options = [:ignore_whitespace_change, + :disable_pathspec_match, :paths, :max_files, :max_lines, :limits, :expanded] if default_options diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb index d97e85364c2..0d712f39aea 100644 --- a/spec/lib/gitlab/git/diff_spec.rb +++ b/spec/lib/gitlab/git/diff_spec.rb @@ -241,7 +241,7 @@ EOT end describe '.filter_diff_options' do - let(:options) { { max_size: 100, invalid_opt: true } } + let(:options) { { max_files: 100, invalid_opt: true } } context "without default options" do let(:filtered_options) { described_class.filter_diff_options(options) } @@ -253,7 +253,7 @@ EOT context "with default options" do let(:filtered_options) do - default_options = { max_size: 5, bad_opt: 1, ignore_whitespace: true } + default_options = { max_files: 5, bad_opt: 1, ignore_whitespace_change: true } described_class.filter_diff_options(options, default_options) end @@ -263,12 +263,12 @@ EOT end it "should merge with default options" do - expect(filtered_options).to have_key(:ignore_whitespace) + expect(filtered_options).to have_key(:ignore_whitespace_change) end it "should override default options" do - expect(filtered_options).to have_key(:max_size) - expect(filtered_options[:max_size]).to eq(100) + expect(filtered_options).to have_key(:max_files) + expect(filtered_options[:max_files]).to eq(100) end end end From 4430afc18c19cfdb36137f28e62d4e41e29d6e53 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Wed, 12 Jul 2017 10:26:57 -0700 Subject: [PATCH 46/61] Truncate job on environment view --- .../javascripts/environments/components/environment_item.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index b25113e0fc6..d8b1b2f1b92 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -498,9 +498,9 @@ export default { From a90ca93c1f3c88d8c6339dddb2e6c35296382e9f Mon Sep 17 00:00:00 2001 From: Ruben Davila Date: Wed, 12 Jul 2017 12:38:02 -0500 Subject: [PATCH 47/61] Fix wrong helper used for adding context for translations. Additionally some missing translations were added --- app/helpers/application_settings_helper.rb | 4 +- locale/es/gitlab.po | 88 ++++++++++++++++++++-- locale/gitlab.pot | 12 +-- 3 files changed, 89 insertions(+), 15 deletions(-) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index f652f4901b7..45b10f61f33 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -35,7 +35,7 @@ module ApplicationSettingsHelper # Return a group of checkboxes that use Bootstrap's button plugin for a # toggle button effect. def restricted_level_checkboxes(help_block_id, checkbox_name) - Gitlab::VisibilityLevel.options.map do |name, level| + Gitlab::VisibilityLevel.values.map do |level| checked = restricted_visibility_levels(true).include?(level) css_class = checked ? 'active' : '' tag_name = "application_setting_visibility_level_#{level}" @@ -44,7 +44,7 @@ module ApplicationSettingsHelper check_box_tag(checkbox_name, level, checked, autocomplete: 'off', 'aria-describedby' => help_block_id, - id: tag_name) + visibility_level_icon(level) + name + id: tag_name) + visibility_level_icon(level) + visibility_level_label(level) end end end diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po index cec086b871c..760a60f89d4 100644 --- a/locale/es/gitlab.po +++ b/locale/es/gitlab.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2017-06-21 12:09-0500\n" +"PO-Revision-Date: 2017-07-12 12:35-0500\n" "Language-Team: Spanish\n" "Language: es\n" "MIME-Version: 1.0\n" @@ -17,19 +17,27 @@ msgstr "" "Last-Translator: Bob Van Landuyt \n" "X-Generator: Poedit 2.0.2\n" -msgid "%d additional commit has been omitted to prevent performance issues." -msgid_plural "%d additional commits have been omitted to prevent performance issues." -msgstr[0] "%d cambio adicional ha sido omitido para evitar problemas de rendimiento." -msgstr[1] "%d cambios adicionales han sido omitidos para evitar problemas de rendimiento." - msgid "%d commit" msgid_plural "%d commits" msgstr[0] "%d cambio" msgstr[1] "%d cambios" +msgid "%s additional commit has been omitted to prevent performance issues." +msgid_plural "%s additional commits have been omitted to prevent performance issues." +msgstr[0] "%s cambio adicional ha sido omitido para evitar problemas de rendimiento." +msgstr[1] "%s cambios adicionales han sido omitidos para evitar problemas de rendimiento." + msgid "%{commit_author_link} committed %{commit_timeago}" msgstr "%{commit_author_link} cambió %{commit_timeago}" +msgid "1 pipeline" +msgid_plural "%d pipelines" +msgstr[0] "1 pipeline" +msgstr[1] "%d pipelines" + +msgid "A collection of graphs regarding Continuous Integration" +msgstr "Una colección de gráficos sobre Integración Continua" + msgid "About auto deploy" msgstr "Acerca del auto despliegue" @@ -184,6 +192,9 @@ msgid_plural "Commits" msgstr[0] "Cambio" msgstr[1] "Cambios" +msgid "Commit duration in minutes for last 30 commits" +msgstr "Duración de los cambios en minutos para los últimos 30" + msgid "Commit message" msgstr "Mensaje del cambio" @@ -223,6 +234,9 @@ msgstr "Copiar SHA del cambio al portapapeles" msgid "Create New Directory" msgstr "Crear Nuevo Directorio" +msgid "Create a personal access token on your account to pull or push via %{protocol}." +msgstr "Crear un token de acceso personal en tu cuenta para actualizar o enviar a través de %{protocol}." + msgid "Create directory" msgstr "Crear directorio" @@ -241,6 +255,9 @@ msgstr "Bifurcar" msgid "CreateTag|Tag" msgstr "Etiqueta" +msgid "CreateTokenToCloneLink|create a personal access token" +msgstr "crear un token de acceso personal" + msgid "Cron Timezone" msgstr "Zona horaria del Cron" @@ -401,6 +418,15 @@ msgstr "Patrón de intervalo" msgid "Introducing Cycle Analytics" msgstr "Introducción a Cycle Analytics" +msgid "Jobs for last month" +msgstr "Trabajos del mes pasado" + +msgid "Jobs for last week" +msgstr "Trabajos de la semana pasada" + +msgid "Jobs for last year" +msgstr "Trabajos del año pasado" + msgid "LFSStatus|Disabled" msgstr "Deshabilitado" @@ -566,6 +592,21 @@ msgstr "Programación del Pipeline" msgid "Pipeline Schedules" msgstr "Programaciones de los Pipelines" +msgid "PipelineCharts|Failed:" +msgstr "Fallidos:" + +msgid "PipelineCharts|Overall statistics" +msgstr "Estadísticas generales" + +msgid "PipelineCharts|Success ratio:" +msgstr "Ratio de éxito" + +msgid "PipelineCharts|Successful:" +msgstr "Exitosos:" + +msgid "PipelineCharts|Total:" +msgstr "Total:" + msgid "PipelineSchedules|Activated" msgstr "Activado" @@ -578,6 +619,12 @@ msgstr "Todos" msgid "PipelineSchedules|Inactive" msgstr "Inactivos" +msgid "PipelineSchedules|Input variable key" +msgstr "Ingrese nombre de clave" + +msgid "PipelineSchedules|Input variable value" +msgstr "Ingrese el valor de la variable" + msgid "PipelineSchedules|Next Run" msgstr "Próxima Ejecución" @@ -585,7 +632,10 @@ msgid "PipelineSchedules|None" msgstr "Ninguno" msgid "PipelineSchedules|Provide a short description for this pipeline" -msgstr "Proporcione una breve descripción para este pipeline" +msgstr "Proporcione una descripción breve para este pipeline" + +msgid "PipelineSchedules|Remove variable row" +msgstr "Eliminar fila de variable" msgid "PipelineSchedules|Take ownership" msgstr "Tomar posesión" @@ -593,9 +643,24 @@ msgstr "Tomar posesión" msgid "PipelineSchedules|Target" msgstr "Destino" +msgid "PipelineSchedules|Variables" +msgstr "Variables" + msgid "PipelineSheduleIntervalPattern|Custom" msgstr "Personalizado" +msgid "Pipelines" +msgstr "Pipelines" + +msgid "Pipelines charts" +msgstr "Gráficos de los pipelines" + +msgid "Pipeline|all" +msgstr "todos" + +msgid "Pipeline|success" +msgstr "exitósos" + msgid "Pipeline|with stage" msgstr "con etapa" @@ -1003,6 +1068,15 @@ msgstr "No hay suficientes datos para mostrar en esta etapa." msgid "Withdraw Access Request" msgstr "Retirar Solicitud de Acceso" +msgid "" +"You are going to remove %{group_name}.\n" +"Removed groups CANNOT be restored!\n" +"Are you ABSOLUTELY sure?" +msgstr "" +"Va a eliminar %{group_name}.\n" +"¡El grupo eliminado NO puede ser restaurado!\n" +"¿Estás TOTALMENTE seguro?" + msgid "" "You are going to remove %{project_name_with_namespace}.\n" "Removed project CANNOT be restored!\n" diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6066314b32e..8f33c494de9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: gitlab 1.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-07-05 08:50-0500\n" -"PO-Revision-Date: 2017-07-05 08:50-0500\n" +"POT-Creation-Date: 2017-07-12 12:31-0500\n" +"PO-Revision-Date: 2017-07-12 12:31-0500\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" @@ -18,13 +18,13 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -msgid "%d additional commit has been omitted to prevent performance issues." -msgid_plural "%d additional commits have been omitted to prevent performance issues." +msgid "%d commit" +msgid_plural "%d commits" msgstr[0] "" msgstr[1] "" -msgid "%d commit" -msgid_plural "%d commits" +msgid "%s additional commit has been omitted to prevent performance issues." +msgid_plural "%s additional commits have been omitted to prevent performance issues." msgstr[0] "" msgstr[1] "" From 0c75742fbd936c9c058b249fc05e0964870f53d6 Mon Sep 17 00:00:00 2001 From: Balasankar C Date: Thu, 13 Jul 2017 10:28:10 +0530 Subject: [PATCH 48/61] Fix i18n string in commit page options dropdown --- app/views/projects/commit/_commit_box.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml index 572c368990e..45109f2c58b 100644 --- a/app/views/projects/commit/_commit_box.html.haml +++ b/app/views/projects/commit/_commit_box.html.haml @@ -30,7 +30,7 @@ %ul.dropdown-menu.dropdown-menu-align-right %li.visible-xs-block.visible-sm-block = link_to project_tree_path(@project, @commit) do - _('Browse Files') + #{ _('Browse Files') } - unless @commit.has_been_reverted?(current_user) %li.clearfix = revert_commit_link(@commit, project_commit_path(@project, @commit.id), has_tooltip: false) From 6900dff23d70ea59b13b299a9966378ed3e0358f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 13 Jul 2017 09:54:41 +0100 Subject: [PATCH 49/61] Reload page after changing navigation preference Closes #34968 --- app/assets/javascripts/experimental_flags.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js index dbd3843cef7..6ee65ca72f9 100644 --- a/app/assets/javascripts/experimental_flags.js +++ b/app/assets/javascripts/experimental_flags.js @@ -7,5 +7,8 @@ export default () => { Cookies.set(el.name, el.value, { expires: 365 * 10, }); + + document.body.scrollTop = 0; + window.location.reload(); }); }; From 5db156544c8fbec6da35b60fb001f68ba79f5eee Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 13 Jul 2017 10:31:00 +0100 Subject: [PATCH 50/61] Prevent GitLab issue tracker spec from failing later specs --- .../gitlab_issue_tracker_service_spec.rb | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb index dcb70ee28a8..6ee30e86495 100644 --- a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -23,38 +23,29 @@ describe GitlabIssueTrackerService, models: true do describe 'project and issue urls' do let(:project) { create(:empty_project) } + let(:service) { project.create_gitlab_issue_tracker_service(active: true) } context 'with absolute urls' do before do - GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root" - @service = project.create_gitlab_issue_tracker_service(active: true) - end - - after do - @service.destroy! + allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root") end it 'gives the correct path' do - expect(@service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues") - expect(@service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new") - expect(@service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432") + expect(service.project_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues") + expect(service.new_issue_url).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/new") + expect(service.issue_url(432)).to eq("http://#{Gitlab.config.gitlab.host}/gitlab/root/#{project.path_with_namespace}/issues/432") end end context 'with relative urls' do before do - GitlabIssueTrackerService.default_url_options[:script_name] = "/gitlab/root" - @service = project.create_gitlab_issue_tracker_service(active: true) - end - - after do - @service.destroy! + allow(GitlabIssueTrackerService).to receive(:default_url_options).and_return(script_name: "/gitlab/root") end it 'gives the correct path' do - expect(@service.project_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues") - expect(@service.new_issue_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new") - expect(@service.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432") + expect(service.project_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues") + expect(service.new_issue_path).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new") + expect(service.issue_path(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432") end end end From 3ee48e422defaedd69946c607bd8d3672e510375 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 13 Jul 2017 09:58:05 +0200 Subject: [PATCH 51/61] Enable all feature flags by default in specs Otherwise some features would go untested in non-specific contexts I did need to disable the `gitlab_git_diff_size_limit_increase`-feature in some specs since we depend on diffs being expandable while the file we are testing on is smaller than the increased limit. --- spec/features/merge_requests/conflicts_spec.rb | 5 +++++ spec/features/projects/diffs/diff_show_spec.rb | 4 ++++ spec/lib/gitlab/git/diff_spec.rb | 4 ++-- spec/spec_helper.rb | 3 +++ spec/support/stub_feature_flags.rb | 8 ++++++++ 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 spec/support/stub_feature_flags.rb diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 3e01ea69122..5c0909b6a59 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -4,6 +4,11 @@ feature 'Merge request conflict resolution', js: true, feature: true do let(:user) { create(:user) } let(:project) { create(:project) } + before do + # In order to have the diffs collapsed, we need to disable the increase feature + stub_feature_flags(gitlab_git_diff_size_limit_increase: false) + end + def create_merge_request(source_branch) create(:merge_request, source_branch: source_branch, target_branch: 'conflict-start', source_project: project) do |mr| mr.mark_as_unmergeable diff --git a/spec/features/projects/diffs/diff_show_spec.rb b/spec/features/projects/diffs/diff_show_spec.rb index b528b283495..4baccb24806 100644 --- a/spec/features/projects/diffs/diff_show_spec.rb +++ b/spec/features/projects/diffs/diff_show_spec.rb @@ -110,6 +110,10 @@ feature 'Diff file viewer', :js, feature: true do context 'binary file that appears to be text in the first 1024 bytes' do before do + # The file we're visiting is smaller than 10 KB and we want it collapsed + # so we need to disable the size increase feature. + stub_feature_flags(gitlab_git_diff_size_limit_increase: false) + visit_commit('7b1cf4336b528e0f3d1d140ee50cafdbc703597c') end diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb index d97e85364c2..81a996f6f45 100644 --- a/spec/lib/gitlab/git/diff_spec.rb +++ b/spec/lib/gitlab/git/diff_spec.rb @@ -34,7 +34,7 @@ EOT describe 'size limit feature toggles' do context 'when the feature gitlab_git_diff_size_limit_increase is enabled' do before do - Feature.enable('gitlab_git_diff_size_limit_increase') + stub_feature_flags(gitlab_git_diff_size_limit_increase: true) end it 'returns 200 KB for size_limit' do @@ -48,7 +48,7 @@ EOT context 'when the feature gitlab_git_diff_size_limit_increase is disabled' do before do - Feature.disable('gitlab_git_diff_size_limit_increase') + stub_feature_flags(gitlab_git_diff_size_limit_increase: false) end it 'returns 100 KB for size_limit' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3c142764e28..b8ed1e18de0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -59,6 +59,7 @@ RSpec.configure do |config| config.include ApiHelpers, :api config.include Gitlab::Routing, type: :routing config.include MigrationsHelpers, :migration + config.include StubFeatureFlags config.infer_spec_type_from_file_location! @@ -79,6 +80,8 @@ RSpec.configure do |config| config.before(:example) do # Skip pre-receive hook check so we can use the web editor and merge. allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil]) + # Enable all features by default for testing + allow(Feature).to receive(:enabled?) { true } end config.before(:example, :request_store) do diff --git a/spec/support/stub_feature_flags.rb b/spec/support/stub_feature_flags.rb new file mode 100644 index 00000000000..b96338bf548 --- /dev/null +++ b/spec/support/stub_feature_flags.rb @@ -0,0 +1,8 @@ +module StubFeatureFlags + def stub_feature_flags(features) + features.each do |feature_name, enabled| + allow(Feature).to receive(:enabled?).with(feature_name) { enabled } + allow(Feature).to receive(:enabled?).with(feature_name.to_s) { enabled } + end + end +end From 672a68d3724bcae676d18244c85566e7d664a169 Mon Sep 17 00:00:00 2001 From: Robin Bobbitt Date: Tue, 27 Jun 2017 14:02:09 -0400 Subject: [PATCH 52/61] Fixes needed when GitLab sign-in is not enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When sign-in is disabled: - skip password expiration checks - prevent password reset requests - don’t show Password tab in User Settings - don’t allow login with username/password for Git over HTTP requests - render 404 on requests to Profiles::PasswordsController --- .../admin/application_settings_controller.rb | 2 +- app/controllers/application_controller.rb | 2 +- app/controllers/passwords_controller.rb | 12 +-- .../profiles/passwords_controller.rb | 2 +- app/controllers/sessions_controller.rb | 2 +- app/helpers/application_settings_helper.rb | 2 +- app/helpers/button_helper.rb | 4 +- app/helpers/projects_helper.rb | 4 +- app/models/application_setting.rb | 2 +- app/models/user.rb | 12 ++- .../application_settings/_form.html.haml | 6 +- app/views/devise/sessions/new.html.haml | 6 +- app/views/devise/shared/_signin_box.html.haml | 4 +- app/views/devise/shared/_tabs_ldap.html.haml | 4 +- .../devise/shared/_tabs_normal.html.haml | 2 +- app/views/layouts/nav/_profile.html.haml | 2 +- .../fixes-for-internal-auth-disabled.yml | 4 + config/initializers/1_settings.rb | 2 +- ...bled_to_password_authentication_enabled.rb | 15 ++++ ...lication_settings_signin_enabled_rename.rb | 15 ++++ db/schema.rb | 2 +- doc/api/settings.md | 6 +- lib/api/entities.rb | 3 +- lib/api/settings.rb | 9 ++- lib/api/v3/entities.rb | 3 +- lib/api/v3/settings.rb | 14 +++- lib/gitlab/auth.rb | 6 +- .../application_controller_spec.rb | 9 +++ spec/controllers/passwords_controller_spec.rb | 29 +++++++ spec/features/profiles/password_spec.rb | 80 +++++++++++++------ spec/features/projects/no_password_spec.rb | 2 +- spec/helpers/button_helper_spec.rb | 2 +- spec/helpers/projects_helper_spec.rb | 4 +- spec/lib/gitlab/auth_spec.rb | 12 ++- .../gitlab/fake_application_settings_spec.rb | 10 +-- spec/models/user_spec.rb | 22 +++++ spec/requests/api/settings_spec.rb | 6 +- spec/requests/api/v3/settings_spec.rb | 6 +- spec/requests/git_http_spec.rb | 2 +- spec/requests/jwt_controller_spec.rb | 2 +- 40 files changed, 247 insertions(+), 86 deletions(-) create mode 100644 changelogs/unreleased/fixes-for-internal-auth-disabled.yml create mode 100644 db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb create mode 100644 db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb create mode 100644 spec/controllers/passwords_controller_spec.rb diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 1cc060e4de8..c1bc4c0d675 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -113,6 +113,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :html_emails_enabled, :koding_enabled, :koding_url, + :password_authentication_enabled, :plantuml_enabled, :plantuml_url, :max_artifacts_size, @@ -135,7 +136,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :require_two_factor_authentication, :session_expire_delay, :sign_in_text, - :signin_enabled, :signup_enabled, :sentry_dsn, :sentry_enabled, diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index db7edbd619b..43462b13903 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -170,7 +170,7 @@ class ApplicationController < ActionController::Base end def check_password_expiration - if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? + if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && current_user.allow_password_authentication? return redirect_to new_profile_password_path end end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index a8575e037e4..aa8cf630032 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,6 +1,8 @@ class PasswordsController < Devise::PasswordsController + include Gitlab::CurrentSettings + before_action :resource_from_email, only: [:create] - before_action :prevent_ldap_reset, only: [:create] + before_action :check_password_authentication_available, only: [:create] before_action :throttle_reset, only: [:create] def edit @@ -25,7 +27,7 @@ class PasswordsController < Devise::PasswordsController def update super do |resource| - if resource.valid? && resource.require_password? + if resource.valid? && resource.require_password_creation? resource.update_attribute(:password_automatically_set, false) end end @@ -38,11 +40,11 @@ class PasswordsController < Devise::PasswordsController self.resource = resource_class.find_by_email(email) end - def prevent_ldap_reset - return unless resource && resource.ldap_user? + def check_password_authentication_available + return if current_application_settings.password_authentication_enabled? && (resource.nil? || resource.allow_password_authentication?) redirect_to after_sending_reset_password_instructions_path_for(resource_name), - alert: "Cannot reset password for LDAP user." + alert: "Password authentication is unavailable." end def throttle_reset diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index 10145bae0d3..c423761ab24 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -77,7 +77,7 @@ class Profiles::PasswordsController < Profiles::ApplicationController end def authorize_change_password! - return render_404 if @user.ldap_user? + render_404 unless @user.allow_password_authentication? end def user_params diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index f39441a281e..e0e72170d1e 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -58,7 +58,7 @@ class SessionsController < Devise::SessionsController user = User.admins.last - return unless user && user.require_password? + return unless user && user.require_password_creation? Users::UpdateService.new(user).execute do |user| @token = user.generate_reset_token diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index f652f4901b7..3ffcd817768 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -1,7 +1,7 @@ module ApplicationSettingsHelper delegate :gravatar_enabled?, :signup_enabled?, - :signin_enabled?, + :password_authentication_enabled?, :akismet_enabled?, :koding_enabled?, to: :current_application_settings diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb index ba84dbe4a7a..bf9ad95b7c2 100644 --- a/app/helpers/button_helper.rb +++ b/app/helpers/button_helper.rb @@ -50,12 +50,12 @@ module ButtonHelper def http_clone_button(project, placement = 'right', append_link: true) klass = 'http-selector' - klass << ' has-tooltip' if current_user.try(:require_password?) || current_user.try(:require_personal_access_token?) + klass << ' has-tooltip' if current_user.try(:require_password_creation?) || current_user.try(:require_personal_access_token_creation_for_git_auth?) protocol = gitlab_config.protocol.upcase tooltip_title = - if current_user.try(:require_password?) + if current_user.try(:require_password_creation?) _("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol } else _("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol } diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 25969adb649..6a62c7ab0be 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -214,11 +214,11 @@ module ProjectsHelper def show_no_password_message? cookies[:hide_no_password_message].blank? && !current_user.hide_no_password && - ( current_user.require_password? || current_user.require_personal_access_token? ) + ( current_user.require_password_creation? || current_user.require_personal_access_token_creation_for_git_auth? ) end def link_to_set_password - if current_user.require_password? + if current_user.require_password_creation? link_to s_('SetPasswordToCloneLink|set a password'), edit_profile_password_path else link_to s_('CreateTokenToCloneLink|create a personal access token'), profile_personal_access_tokens_path diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 98e3906a932..898ce45f60e 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -237,6 +237,7 @@ class ApplicationSetting < ActiveRecord::Base koding_url: nil, max_artifacts_size: Settings.artifacts['max_size'], max_attachment_size: Settings.gitlab['max_attachment_size'], + password_authentication_enabled: Settings.gitlab['password_authentication_enabled'], performance_bar_allowed_group_id: nil, plantuml_enabled: false, plantuml_url: nil, @@ -251,7 +252,6 @@ class ApplicationSetting < ActiveRecord::Base shared_runners_text: nil, sidekiq_throttling_enabled: false, sign_in_text: nil, - signin_enabled: Settings.gitlab['signin_enabled'], signup_enabled: Settings.gitlab['signup_enabled'], terminal_max_session_time: 0, two_factor_grace_period: 48, diff --git a/app/models/user.rb b/app/models/user.rb index 4b01c2f19f0..e622f63b54d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -580,16 +580,20 @@ class User < ActiveRecord::Base keys.count == 0 && Gitlab::ProtocolAccess.allowed?('ssh') end - def require_password? - password_automatically_set? && !ldap_user? && current_application_settings.signin_enabled? + def require_password_creation? + password_automatically_set? && allow_password_authentication? end - def require_personal_access_token? - return false if current_application_settings.signin_enabled? || ldap_user? + def require_personal_access_token_creation_for_git_auth? + return false if allow_password_authentication? || ldap_user? PersonalAccessTokensFinder.new(user: self, impersonation: false, state: 'active').execute.none? end + def allow_password_authentication? + !ldap_user? && current_application_settings.password_authentication_enabled? + end + def can_change_username? gitlab_config.username_changing_enabled end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 7f1e13c7989..26f7c1a473a 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -145,9 +145,9 @@ .form-group .col-sm-offset-2.col-sm-10 .checkbox - = f.label :signin_enabled do - = f.check_box :signin_enabled - Sign-in enabled + = f.label :password_authentication_enabled do + = f.check_box :password_authentication_enabled + Password authentication enabled - if omniauth_enabled? && button_based_providers.any? .form-group = f.label :enabled_oauth_sign_in_sources, 'Enabled OAuth sign-in sources', class: 'control-label col-sm-2' diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index af87129e49e..dd61dcf2a7b 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -6,15 +6,15 @@ - else = render 'devise/shared/tabs_normal' .tab-content - - if signin_enabled? || ldap_enabled? || crowd_enabled? + - if password_authentication_enabled? || ldap_enabled? || crowd_enabled? = render 'devise/shared/signin_box' -# Signup only makes sense if you can also sign-in - - if signin_enabled? && signup_enabled? + - if password_authentication_enabled? && signup_enabled? = render 'devise/shared/signup_box' -# Show a message if none of the mechanisms above are enabled - - if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) + - if !password_authentication_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) %div No authentication methods configured. diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml index da4769e214e..3b06008febe 100644 --- a/app/views/devise/shared/_signin_box.html.haml +++ b/app/views/devise/shared/_signin_box.html.haml @@ -7,12 +7,12 @@ .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) } .login-body = render 'devise/sessions/new_ldap', server: server - - if signin_enabled? + - if password_authentication_enabled? .login-box.tab-pane{ id: 'ldap-standard', role: 'tabpanel' } .login-body = render 'devise/sessions/new_base' -- elsif signin_enabled? +- elsif password_authentication_enabled? .login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' } .login-body = render 'devise/sessions/new_base' diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml index dd34600490e..6d0243a325d 100644 --- a/app/views/devise/shared/_tabs_ldap.html.haml +++ b/app/views/devise/shared/_tabs_ldap.html.haml @@ -5,9 +5,9 @@ - @ldap_servers.each_with_index do |server, i| %li{ class: active_when(i.zero? && !crowd_enabled?) } = link_to server['label'], "##{server['provider_name']}", 'data-toggle' => 'tab' - - if signin_enabled? + - if password_authentication_enabled? %li = link_to 'Standard', '#ldap-standard', 'data-toggle' => 'tab' - - if signin_enabled? && signup_enabled? + - if password_authentication_enabled? && signup_enabled? %li = link_to 'Register', '#register-pane', 'data-toggle' => 'tab' diff --git a/app/views/devise/shared/_tabs_normal.html.haml b/app/views/devise/shared/_tabs_normal.html.haml index c225d800a98..212856c0676 100644 --- a/app/views/devise/shared/_tabs_normal.html.haml +++ b/app/views/devise/shared/_tabs_normal.html.haml @@ -1,6 +1,6 @@ %ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' } %li.active{ role: 'presentation' } %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in - - if signin_enabled? && signup_enabled? + - if password_authentication_enabled? && signup_enabled? %li{ role: 'presentation' } %a{ href: '#register-pane', data: { toggle: 'tab' }, role: 'tab' } Register diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml index ae1e1361f0f..424905ea890 100644 --- a/app/views/layouts/nav/_profile.html.haml +++ b/app/views/layouts/nav/_profile.html.haml @@ -29,7 +29,7 @@ = link_to profile_emails_path, title: 'Emails' do %span Emails - - unless current_user.ldap_user? + - if current_user.allow_password_authentication? = nav_link(controller: :passwords) do = link_to edit_profile_password_path, title: 'Password' do %span diff --git a/changelogs/unreleased/fixes-for-internal-auth-disabled.yml b/changelogs/unreleased/fixes-for-internal-auth-disabled.yml new file mode 100644 index 00000000000..188d2770455 --- /dev/null +++ b/changelogs/unreleased/fixes-for-internal-auth-disabled.yml @@ -0,0 +1,4 @@ +--- +title: Fixes needed when GitLab sign-in is not enabled +merge_request: 12491 +author: Robin Bobbitt diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index fa33e602e93..0ab2ecae856 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -223,7 +223,7 @@ rescue ArgumentError # no user configured end Settings.gitlab['time_zone'] ||= nil Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? -Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? +Settings.gitlab['password_authentication_enabled'] ||= true if Settings.gitlab['password_authentication_enabled'].nil? Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing))(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil? diff --git a/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb b/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb new file mode 100644 index 00000000000..858b3bebace --- /dev/null +++ b/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb @@ -0,0 +1,15 @@ +class RenameApplicationSettingsSigninEnabledToPasswordAuthenticationEnabled < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + rename_column_concurrently :application_settings, :signin_enabled, :password_authentication_enabled + end + + def down + cleanup_concurrent_column_rename :application_settings, :password_authentication_enabled, :signin_enabled + end +end diff --git a/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb b/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb new file mode 100644 index 00000000000..52a773ddfee --- /dev/null +++ b/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb @@ -0,0 +1,15 @@ +class CleanupApplicationSettingsSigninEnabledRename < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + cleanup_concurrent_column_rename :application_settings, :signin_enabled, :password_authentication_enabled + end + + def down + rename_column_concurrently :application_settings, :password_authentication_enabled, :signin_enabled + end +end diff --git a/db/schema.rb b/db/schema.rb index 3dbe52c9c80..5264fc99557 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -41,7 +41,6 @@ ActiveRecord::Schema.define(version: 20170707184244) do create_table "application_settings", force: :cascade do |t| t.integer "default_projects_limit" t.boolean "signup_enabled" - t.boolean "signin_enabled" t.boolean "gravatar_enabled" t.text "sign_in_text" t.datetime "created_at" @@ -127,6 +126,7 @@ ActiveRecord::Schema.define(version: 20170707184244) do t.boolean "help_page_hide_commercial_content", default: false t.string "help_page_support_url" t.integer "performance_bar_allowed_group_id" + t.boolean "password_authentication_enabled" end create_table "audit_events", force: :cascade do |t| diff --git a/doc/api/settings.md b/doc/api/settings.md index eefbdda42ce..0b4cc98cea6 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -25,7 +25,7 @@ Example response: "id" : 1, "default_branch_protection" : 2, "restricted_visibility_levels" : [], - "signin_enabled" : true, + "password_authentication_enabled" : true, "after_sign_out_path" : null, "max_attachment_size" : 10, "user_oauth_applications" : true, @@ -63,7 +63,7 @@ PUT /application/settings | --------- | ---- | :------: | ----------- | | `default_projects_limit` | integer | no | Project limit per user. Default is `100000` | | `signup_enabled` | boolean | no | Enable registration. Default is `true`. | -| `signin_enabled` | boolean | no | Enable login via a GitLab account. Default is `true`. | +| `password_authentication_enabled` | boolean | no | Enable authentication via a GitLab account password. Default is `true`. | | `gravatar_enabled` | boolean | no | Enable Gravatar | | `sign_in_text` | string | no | Text on login page | | `home_page_url` | string | no | Redirect to this URL when not logged in | @@ -102,7 +102,7 @@ Example response: "id": 1, "default_projects_limit": 100000, "signup_enabled": true, - "signin_enabled": true, + "password_authentication_enabled": true, "gravatar_enabled": true, "sign_in_text": "", "created_at": "2015-06-12T15:51:55.432Z", diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 945f2821d72..57c561b3724 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -614,7 +614,8 @@ module API expose :id expose :default_projects_limit expose :signup_enabled - expose :signin_enabled + expose :password_authentication_enabled + expose :password_authentication_enabled, as: :signin_enabled expose :gravatar_enabled expose :sign_in_text expose :after_sign_up_text diff --git a/lib/api/settings.rb b/lib/api/settings.rb index d598f9a62a2..b19095d1252 100644 --- a/lib/api/settings.rb +++ b/lib/api/settings.rb @@ -65,6 +65,7 @@ module API :shared_runners_enabled, :sidekiq_throttling_enabled, :sign_in_text, + :password_authentication_enabled, :signin_enabled, :signup_enabled, :terminal_max_session_time, @@ -95,7 +96,9 @@ module API requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com' end optional :after_sign_up_text, type: String, desc: 'Text shown after sign up' - optional :signin_enabled, type: Boolean, desc: 'Flag indicating if sign in is enabled' + optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' + optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' + mutually_exclusive :password_authentication_enabled, :signin_enabled optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication' given require_two_factor_authentication: ->(val) { val } do requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication' @@ -176,6 +179,10 @@ module API put "application/settings" do attrs = declared_params(include_missing: false) + if attrs.has_key?(:signin_enabled) + attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled) + end + if current_settings.update_attributes(attrs) present current_settings, with: Entities::ApplicationSetting else diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index c848f52723b..3759250f7f6 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -161,7 +161,8 @@ module API expose :id expose :default_projects_limit expose :signup_enabled - expose :signin_enabled + expose :password_authentication_enabled + expose :password_authentication_enabled, as: :signin_enabled expose :gravatar_enabled expose :sign_in_text expose :after_sign_up_text diff --git a/lib/api/v3/settings.rb b/lib/api/v3/settings.rb index 748d6b97d4f..202011cfcbe 100644 --- a/lib/api/v3/settings.rb +++ b/lib/api/v3/settings.rb @@ -44,7 +44,9 @@ module API requires :domain_blacklist, type: String, desc: 'Users with e-mail addresses that match these domain(s) will NOT be able to sign-up. Wildcards allowed. Use separate lines for multiple entries. Ex: domain.com, *.domain.com' end optional :after_sign_up_text, type: String, desc: 'Text shown after sign up' - optional :signin_enabled, type: Boolean, desc: 'Flag indicating if sign in is enabled' + optional :password_authentication_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' + optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled' + mutually_exclusive :password_authentication_enabled, :signin_enabled optional :require_two_factor_authentication, type: Boolean, desc: 'Require all users to setup Two-factor authentication' given require_two_factor_authentication: ->(val) { val } do requires :two_factor_grace_period, type: Integer, desc: 'Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication' @@ -116,7 +118,7 @@ module API :max_attachment_size, :session_expire_delay, :disabled_oauth_sign_in_sources, :user_oauth_applications, :user_default_external, :signup_enabled, :send_user_confirmation_email, :domain_whitelist, :domain_blacklist_enabled, - :after_sign_up_text, :signin_enabled, :require_two_factor_authentication, + :after_sign_up_text, :password_authentication_enabled, :signin_enabled, :require_two_factor_authentication, :home_page_url, :after_sign_out_path, :sign_in_text, :help_page_text, :shared_runners_enabled, :max_artifacts_size, :max_pages_size, :container_registry_token_expire_delay, :metrics_enabled, :sidekiq_throttling_enabled, :recaptcha_enabled, @@ -126,7 +128,13 @@ module API :housekeeping_enabled, :terminal_max_session_time end put "application/settings" do - if current_settings.update_attributes(declared_params(include_missing: false)) + attrs = declared_params(include_missing: false) + + if attrs.has_key?(:signin_enabled) + attrs[:password_authentication_enabled] = attrs.delete(:signin_enabled) + end + + if current_settings.update_attributes(attrs) present current_settings, with: Entities::ApplicationSetting else render_validation_error!(current_settings) diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index ccb5d886bab..9bed81e7327 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -37,7 +37,7 @@ module Gitlab rate_limit!(ip, success: result.success?, login: login) Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) - return result if result.success? || current_application_settings.signin_enabled? || Gitlab::LDAP::Config.enabled? + return result if result.success? || current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled? # If sign-in is disabled and LDAP is not configured, recommend a # personal access token on failed auth attempts @@ -48,6 +48,10 @@ module Gitlab # Avoid resource intensive login checks if password is not provided return unless password.present? + # Nothing to do here if internal auth is disabled and LDAP is + # not configured + return unless current_application_settings.password_authentication_enabled? || Gitlab::LDAP::Config.enabled? + Gitlab::Auth::UniqueIpsLimiter.limit_user! do user = User.by_login(login) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index a2720c9b81e..1641bddea11 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -30,6 +30,15 @@ describe ApplicationController do expect(controller).not_to receive(:redirect_to) controller.send(:check_password_expiration) end + + it 'does not redirect if the user is over their password expiry but sign-in is disabled' do + stub_application_setting(password_authentication_enabled: false) + user.password_expires_at = Time.new(2002) + allow(controller).to receive(:current_user).and_return(user) + expect(controller).not_to receive(:redirect_to) + + controller.send(:check_password_expiration) + end end describe "#authenticate_user_from_token!" do diff --git a/spec/controllers/passwords_controller_spec.rb b/spec/controllers/passwords_controller_spec.rb new file mode 100644 index 00000000000..2955d01fad0 --- /dev/null +++ b/spec/controllers/passwords_controller_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe PasswordsController do + describe '#check_password_authentication_available' do + before do + @request.env["devise.mapping"] = Devise.mappings[:user] + end + + context 'when password authentication is disabled' do + it 'prevents a password reset' do + stub_application_setting(password_authentication_enabled: false) + + post :create + + expect(flash[:alert]).to eq 'Password authentication is unavailable.' + end + end + + context 'when reset email belongs to an ldap user' do + let(:user) { create(:omniauth_user, provider: 'ldapmain', email: 'ldapuser@gitlab.com') } + + it 'prevents a password reset' do + post :create, user: { email: user.email } + + expect(flash[:alert]).to eq 'Password authentication is unavailable.' + end + end + end +end diff --git a/spec/features/profiles/password_spec.rb b/spec/features/profiles/password_spec.rb index 67975a68ee2..26d6d6658aa 100644 --- a/spec/features/profiles/password_spec.rb +++ b/spec/features/profiles/password_spec.rb @@ -1,44 +1,74 @@ require 'spec_helper' describe 'Profile > Password', feature: true do - let(:user) { create(:user, password_automatically_set: true) } + context 'Password authentication enabled' do + let(:user) { create(:user, password_automatically_set: true) } - before do - sign_in(user) - visit edit_profile_password_path - end + before do + sign_in(user) + visit edit_profile_password_path + end - def fill_passwords(password, confirmation) - fill_in 'New password', with: password - fill_in 'Password confirmation', with: confirmation + def fill_passwords(password, confirmation) + fill_in 'New password', with: password + fill_in 'Password confirmation', with: confirmation - click_button 'Save password' - end + click_button 'Save password' + end - context 'User with password automatically set' do - describe 'User puts different passwords in the field and in the confirmation' do - it 'shows an error message' do - fill_passwords('mypassword', 'mypassword2') + context 'User with password automatically set' do + describe 'User puts different passwords in the field and in the confirmation' do + it 'shows an error message' do + fill_passwords('mypassword', 'mypassword2') - page.within('.alert-danger') do - expect(page).to have_content("Password confirmation doesn't match Password") + page.within('.alert-danger') do + expect(page).to have_content("Password confirmation doesn't match Password") + end + end + + it 'does not contain the current password field after an error' do + fill_passwords('mypassword', 'mypassword2') + + expect(page).to have_no_field('user[current_password]') end end - it 'does not contain the current password field after an error' do - fill_passwords('mypassword', 'mypassword2') + describe 'User puts the same passwords in the field and in the confirmation' do + it 'shows a success message' do + fill_passwords('mypassword', 'mypassword') - expect(page).to have_no_field('user[current_password]') + page.within('.flash-notice') do + expect(page).to have_content('Password was successfully updated. Please login with it') + end + end + end + end + end + + context 'Password authentication unavailable' do + before do + gitlab_sign_in(user) + end + + context 'Regular user' do + let(:user) { create(:user) } + + it 'renders 404 when sign-in is disabled' do + stub_application_setting(password_authentication_enabled: false) + + visit edit_profile_password_path + + expect(page).to have_http_status(404) end end - describe 'User puts the same passwords in the field and in the confirmation' do - it 'shows a success message' do - fill_passwords('mypassword', 'mypassword') + context 'LDAP user' do + let(:user) { create(:omniauth_user, provider: 'ldapmain') } - page.within('.flash-notice') do - expect(page).to have_content('Password was successfully updated. Please login with it') - end + it 'renders 404' do + visit edit_profile_password_path + + expect(page).to have_http_status(404) end end end diff --git a/spec/features/projects/no_password_spec.rb b/spec/features/projects/no_password_spec.rb index 53ac18fa7cc..d22a6daac08 100644 --- a/spec/features/projects/no_password_spec.rb +++ b/spec/features/projects/no_password_spec.rb @@ -30,7 +30,7 @@ feature 'No Password Alert' do let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') } before do - stub_application_setting(signin_enabled?: false) + stub_application_setting(password_authentication_enabled?: false) stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config]) end diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb index 661327d4432..7ecb75da8ce 100644 --- a/spec/helpers/button_helper_spec.rb +++ b/spec/helpers/button_helper_spec.rb @@ -35,7 +35,7 @@ describe ButtonHelper do context 'with internal auth disabled' do before do - stub_application_setting(signin_enabled?: false) + stub_application_setting(password_authentication_enabled?: false) end context 'when user has no personal access tokens' do diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 487d9800707..22fe2a9cabf 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -160,7 +160,7 @@ describe ProjectsHelper do context 'user requires a personal access token' do it 'returns true' do - stub_application_setting(signin_enabled?: false) + stub_application_setting(password_authentication_enabled?: false) expect(helper.show_no_password_message?).to be_truthy end @@ -184,7 +184,7 @@ describe ProjectsHelper do let(:user) { create(:user) } it 'returns link to create a personal access token' do - stub_application_setting(signin_enabled?: false) + stub_application_setting(password_authentication_enabled?: false) expect(helper.link_to_set_password).to match %r{create a personal access token} end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index d09da951869..55780518230 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -206,7 +206,7 @@ describe Gitlab::Auth, lib: true do end it 'throws an error suggesting user create a PAT when internal auth is disabled' do - allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } + allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false } expect { gl_auth.find_for_git_client('foo', 'bar', project: nil, ip: 'ip') }.to raise_error(Gitlab::Auth::MissingPersonalTokenError) end @@ -279,6 +279,16 @@ describe Gitlab::Auth, lib: true do gl_auth.find_with_user_password('ldap_user', 'password') end end + + context "with sign-in disabled" do + before do + stub_application_setting(password_authentication_enabled: false) + end + + it "does not find user by valid login/password" do + expect(gl_auth.find_with_user_password(username, password)).to be_nil + end + end end private diff --git a/spec/lib/gitlab/fake_application_settings_spec.rb b/spec/lib/gitlab/fake_application_settings_spec.rb index b793176d84a..34322c2a693 100644 --- a/spec/lib/gitlab/fake_application_settings_spec.rb +++ b/spec/lib/gitlab/fake_application_settings_spec.rb @@ -1,25 +1,25 @@ require 'spec_helper' describe Gitlab::FakeApplicationSettings do - let(:defaults) { { signin_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } } + let(:defaults) { { password_authentication_enabled: false, foobar: 'asdf', signup_enabled: true, 'test?' => 123 } } subject { described_class.new(defaults) } it 'wraps OpenStruct variables properly' do - expect(subject.signin_enabled).to be_falsey + expect(subject.password_authentication_enabled).to be_falsey expect(subject.signup_enabled).to be_truthy expect(subject.foobar).to eq('asdf') end it 'defines predicate methods' do - expect(subject.signin_enabled?).to be_falsey + expect(subject.password_authentication_enabled?).to be_falsey expect(subject.signup_enabled?).to be_truthy end it 'predicate method changes when value is updated' do - subject.signin_enabled = true + subject.password_authentication_enabled = true - expect(subject.signin_enabled?).to be_truthy + expect(subject.password_authentication_enabled?).to be_truthy end it 'does not define a predicate method' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 448555d2190..927a6d301da 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1920,4 +1920,26 @@ describe User, models: true do user.invalidate_merge_request_cache_counts end end + + describe '#allow_password_authentication?' do + context 'regular user' do + let(:user) { build(:user) } + + it 'returns true when sign-in is enabled' do + expect(user.allow_password_authentication?).to be_truthy + end + + it 'returns false when sign-in is disabled' do + stub_application_setting(password_authentication_enabled: false) + + expect(user.allow_password_authentication?).to be_falsey + end + end + + it 'returns false for ldap user' do + user = create(:omniauth_user, provider: 'ldapmain') + + expect(user.allow_password_authentication?).to be_falsey + end + end end diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index ede48b1c888..b71ac6c30b5 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -10,7 +10,7 @@ describe API::Settings, 'Settings' do expect(response).to have_http_status(200) expect(json_response).to be_an Hash expect(json_response['default_projects_limit']).to eq(42) - expect(json_response['signin_enabled']).to be_truthy + expect(json_response['password_authentication_enabled']).to be_truthy expect(json_response['repository_storage']).to eq('default') expect(json_response['koding_enabled']).to be_falsey expect(json_response['koding_url']).to be_nil @@ -32,7 +32,7 @@ describe API::Settings, 'Settings' do it "updates application settings" do put api("/application/settings", admin), default_projects_limit: 3, - signin_enabled: false, + password_authentication_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com', @@ -46,7 +46,7 @@ describe API::Settings, 'Settings' do help_page_support_url: 'http://example.com/help' expect(response).to have_http_status(200) expect(json_response['default_projects_limit']).to eq(3) - expect(json_response['signin_enabled']).to be_falsey + expect(json_response['password_authentication_enabled']).to be_falsey expect(json_response['repository_storage']).to eq('custom') expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['koding_enabled']).to be_truthy diff --git a/spec/requests/api/v3/settings_spec.rb b/spec/requests/api/v3/settings_spec.rb index 41d039b7da0..291f6dcc2aa 100644 --- a/spec/requests/api/v3/settings_spec.rb +++ b/spec/requests/api/v3/settings_spec.rb @@ -10,7 +10,7 @@ describe API::V3::Settings, 'Settings' do expect(response).to have_http_status(200) expect(json_response).to be_an Hash expect(json_response['default_projects_limit']).to eq(42) - expect(json_response['signin_enabled']).to be_truthy + expect(json_response['password_authentication_enabled']).to be_truthy expect(json_response['repository_storage']).to eq('default') expect(json_response['koding_enabled']).to be_falsey expect(json_response['koding_url']).to be_nil @@ -28,11 +28,11 @@ describe API::V3::Settings, 'Settings' do it "updates application settings" do put v3_api("/application/settings", admin), - default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com', + default_projects_limit: 3, password_authentication_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com', plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com' expect(response).to have_http_status(200) expect(json_response['default_projects_limit']).to eq(3) - expect(json_response['signin_enabled']).to be_falsey + expect(json_response['password_authentication_enabled']).to be_falsey expect(json_response['repository_storage']).to eq('custom') expect(json_response['repository_storages']).to eq(['custom']) expect(json_response['koding_enabled']).to be_truthy diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 185679e1a0f..95c8fabb4ce 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -463,7 +463,7 @@ describe 'Git HTTP requests', lib: true do context 'when internal auth is disabled' do before do - allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } + allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false } end it 'rejects pulls with personal access token error message' do diff --git a/spec/requests/jwt_controller_spec.rb b/spec/requests/jwt_controller_spec.rb index 5e4cf05748e..8d79ea3dd40 100644 --- a/spec/requests/jwt_controller_spec.rb +++ b/spec/requests/jwt_controller_spec.rb @@ -101,7 +101,7 @@ describe JwtController do context 'when internal auth is disabled' do it 'rejects the authorization attempt with personal access token message' do - allow_any_instance_of(ApplicationSetting).to receive(:signin_enabled?) { false } + allow_any_instance_of(ApplicationSetting).to receive(:password_authentication_enabled?) { false } get '/jwt/auth', parameters, headers expect(response).to have_http_status(401) From e578530fa13269526f4243d9109a8fe948a99ae2 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 13 Jul 2017 15:23:55 +0100 Subject: [PATCH 53/61] Move find file URL out of global variable Part of #34903 --- app/assets/javascripts/shortcuts.js | 2 +- app/helpers/projects_helper.rb | 8 ++++++++ app/views/layouts/application.html.haml | 2 +- app/views/layouts/header/_default.html.haml | 5 ----- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/shortcuts.js b/app/assets/javascripts/shortcuts.js index 49d980212d6..e3daa8cf949 100644 --- a/app/assets/javascripts/shortcuts.js +++ b/app/assets/javascripts/shortcuts.js @@ -1,6 +1,5 @@ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, prefer-arrow-callback, consistent-return, object-shorthand, no-unused-vars, one-var, one-var-declaration-per-line, no-else-return, comma-dangle, max-len */ /* global Mousetrap */ -/* global findFileURL */ import Cookies from 'js-cookie'; import findAndFollowLink from './shortcuts_dashboard_navigation'; @@ -20,6 +19,7 @@ import findAndFollowLink from './shortcuts_dashboard_navigation'; const $globalDropdownMenu = $('.global-dropdown-menu'); const $globalDropdownToggle = $('.global-dropdown-toggle'); + const findFileURL = document.body.dataset.findFile; $('.global-dropdown').on('hide.bs.dropdown', () => { $globalDropdownMenu.removeClass('shortcuts'); diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 25969adb649..e1dfed0def3 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -518,4 +518,12 @@ module ProjectsHelper current_application_settings.restricted_visibility_levels || [] end + + def find_file_path + return unless @project && !@project.empty_repo? + + ref = @ref || @project.repository.root_ref + + project_find_file_path(@project, ref) + end end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 81f83b74826..38b95d11fd4 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,7 +1,7 @@ !!! 5 %html{ lang: I18n.locale, class: "#{page_class}" } = render "layouts/head" - %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } } + %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } } = render "layouts/init_auto_complete" if @gfm_form - if show_new_nav? = render "layouts/header/new" diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 25acdb700ef..bc3293fd100 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -91,8 +91,3 @@ = yield :header_content = render 'shared/outdated_browser' - -- if @project && !@project.empty_repo? - - if ref = @ref || @project.repository.root_ref - :javascript - var findFileURL = "#{project_find_file_path(@project, ref)}"; From 6bbdce640cc6880a4d3f0c31034e6789b89638d9 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 13 Jul 2017 15:30:58 +0100 Subject: [PATCH 54/61] missed one... --- app/views/layouts/header/_new.html.haml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/views/layouts/header/_new.html.haml b/app/views/layouts/header/_new.html.haml index 5bc15d68631..4697d91724b 100644 --- a/app/views/layouts/header/_new.html.haml +++ b/app/views/layouts/header/_new.html.haml @@ -84,8 +84,3 @@ = icon('times', class: 'js-navbar-toggle-left', style: 'display: none;') = render 'shared/outdated_browser' - -- if @project && !@project.empty_repo? - - if ref = @ref || @project.repository.root_ref - :javascript - var findFileURL = "#{project_find_file_path(@project, ref)}"; From 170ec4af2b6ec88324415aeba489454e78d66849 Mon Sep 17 00:00:00 2001 From: "Lin Jen-Shin (godfat)" Date: Thu, 13 Jul 2017 15:43:57 +0000 Subject: [PATCH 55/61] Add more notes about developer seeds --- doc/development/rake_tasks.md | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md index fdaaa65fa28..42bb5e8619c 100644 --- a/doc/development/rake_tasks.md +++ b/doc/development/rake_tasks.md @@ -12,6 +12,56 @@ The `setup` task is a alias for `gitlab:setup`. This tasks calls `db:reset` to create the database, calls `add_limits_mysql` that adds limits to the database schema in case of a MySQL database and finally it calls `db:seed_fu` to seed the database. Note: `db:setup` calls `db:seed` but this does nothing. +### Automation + +If you're very sure that you want to **wipe the current database** and refill +seeds, you could: + +``` shell +echo 'yes' | bundle exec rake setup +``` + +To save you from answering `yes` manually. + +### Discard stdout + +Since the script would print a lot of information, it could be slowing down +your terminal, and it would generate more than 20G logs if you just redirect +it to a file. If we don't care about the output, we could just redirect it to +`/dev/null`: + +``` shell +echo 'yes' | bundle exec rake setup > /dev/null +``` + +Note that since you can't see the questions from stdout, you might just want +to `echo 'yes'` to keep it running. It would still print the errors on stderr +so no worries about missing errors. + +### Notes for MySQL + +Since the seeds would contain various UTF-8 characters, such as emojis or so, +we'll need to make sure that we're using `utf8mb4` for all the encoding +settings and `utf8mb4_unicode_ci` for collation. Please check +[MySQL utf8mb4 support](../install/database_mysql.md#mysql-utf8mb4-support) + +Make sure that `config/database.yml` has `encoding: utf8mb4`, too. + +Next, we'll need to update the schema to make the indices fit: + +``` shell +sed -i 's/limit: 255/limit: 191/g' db/schema.rb +``` + +Then run the setup script: + +``` shell +bundle exec rake setup +``` + +To make sure that indices still fit. You could find great details in: +[How to support full Unicode in MySQL databases](https://mathiasbynens.be/notes/mysql-utf8mb4) + ## Run tests In order to run the test you can use the following commands: From f01e71a8b2c52f5c8207532b13c49e2ee9274ce8 Mon Sep 17 00:00:00 2001 From: Thomas Wucher Date: Wed, 12 Jul 2017 09:44:33 +0000 Subject: [PATCH 56/61] Increase width of dropdown menus automatically up to 500 px --- app/assets/stylesheets/framework/dropdowns.scss | 3 ++- .../artifacts-download-dropdown-menu-is-too-narrow.yml | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index dc4ed42544f..3b6bbf3552b 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -186,11 +186,12 @@ .dropdown-menu-nav { display: block; position: absolute; - width: 100%; + width: auto; top: 100%; left: 0; z-index: 9; min-width: 240px; + max-width: 500px; margin-top: 2px; margin-bottom: 0; font-size: 14px; diff --git a/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml b/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml new file mode 100644 index 00000000000..7d47c60e262 --- /dev/null +++ b/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml @@ -0,0 +1,4 @@ +--- +title: Increase width of dropdown menus automatically +merge_request: 12809 +author: Thomas Wucher From 87cb74a7bc98e19c2b2fab5643dfcb591255d077 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 13 Jul 2017 18:29:53 -0700 Subject: [PATCH 57/61] Make sure MergeRequest commit methods work when either compare_commits or merge_request_diff is set --- .../merge_requests/creations_controller.rb | 2 +- app/models/merge_request.rb | 37 ++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb index da058da795e..f35d53896ba 100644 --- a/app/controllers/projects/merge_requests/creations_controller.rb +++ b/app/controllers/projects/merge_requests/creations_controller.rb @@ -107,7 +107,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap @target_project = @merge_request.target_project @source_project = @merge_request.source_project - @commits = @merge_request.compare_commits.reverse + @commits = @merge_request.commits @commit = @merge_request.diff_head_commit @note_counts = Note.where(commit_id: @commits.map(&:id)) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 815c5b43406..e4e7999d0f2 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -32,9 +32,6 @@ class MergeRequest < ActiveRecord::Base after_create :ensure_merge_request_diff, unless: :importing? after_update :reload_diff_if_branch_changed - delegate :commits, :real_size, :commit_shas, :commits_count, - to: :merge_request_diff, prefix: nil - # When this attribute is true some MR validation is ignored # It allows us to close or modify broken merge requests attr_accessor :allow_broken @@ -224,6 +221,36 @@ class MergeRequest < ActiveRecord::Base "#{project.to_reference(from, full: full)}#{reference}" end + def commits + if persisted? + merge_request_diff.commits + elsif compare_commits + compare_commits.reverse + else + [] + end + end + + def commits_count + if persisted? + merge_request_diff.commits_count + elsif compare_commits + compare_commits.size + else + 0 + end + end + + def commit_shas + if persisted? + merge_request_diff.commit_shas + elsif compare_commits + compare_commits.reverse.map(&:sha) + else + [] + end + end + def first_commit merge_request_diff ? merge_request_diff.first_commit : compare_commits.first end @@ -246,9 +273,7 @@ class MergeRequest < ActiveRecord::Base def diff_size # Calling `merge_request_diff.diffs.real_size` will also perform # highlighting, which we don't need here. - return real_size if merge_request_diff - - diffs.real_size + merge_request_diff&.real_size || diffs.real_size end def diff_base_commit From 0e23d1a74ff6283076e9a1d74eccfc5ba6419fd8 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 13 Jul 2017 21:38:26 -0700 Subject: [PATCH 58/61] Handle case when BroadcastMessage.current is nil Somehow Rails.cache.fetch occasionally returns `nil` values, which causes this endpoint to crash. Closes #35094 --- lib/api/internal.rb | 2 +- spec/requests/api/internal_spec.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/api/internal.rb b/lib/api/internal.rb index ef2c08e902c..465363da582 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -101,7 +101,7 @@ module API end get "/broadcast_message" do - if message = BroadcastMessage.current.last + if message = BroadcastMessage.current&.last present message, with: Entities::BroadcastMessage else {} diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 453eb4683a0..beaaf346283 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -35,6 +35,17 @@ describe API::Internal do expect(json_response).to be_empty end end + + context 'nil broadcast message' do + it 'returns nothing' do + allow(BroadcastMessage).to receive(:current).and_return(nil) + + get api('/internal/broadcast_message'), secret_token: secret_token + + expect(response).to have_http_status(200) + expect(json_response).to be_empty + end + end end describe 'GET /internal/broadcast_messages' do From e6cd2353a4123af3183188b200233a32ea7adbdd Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 13 Jul 2017 21:43:44 -0700 Subject: [PATCH 59/61] Handle nil BroadcastMessage.current in the views --- app/views/layouts/_broadcast.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_broadcast.html.haml b/app/views/layouts/_broadcast.html.haml index bcd2f03e83c..e2dbdcbb939 100644 --- a/app/views/layouts/_broadcast.html.haml +++ b/app/views/layouts/_broadcast.html.haml @@ -1,2 +1,2 @@ -- BroadcastMessage.current.each do |message| +- BroadcastMessage.current&.each do |message| = broadcast_message(message) From 9cf5cc310e515494f81e020820003a840f27f9cf Mon Sep 17 00:00:00 2001 From: kamesh Date: Fri, 14 Jul 2017 06:26:14 +0000 Subject: [PATCH 60/61] Fixed typo --- doc/development/fe_guide/droplab/plugins/input_setter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/development/fe_guide/droplab/plugins/input_setter.md b/doc/development/fe_guide/droplab/plugins/input_setter.md index a549603c20d..94f3c8254a8 100644 --- a/doc/development/fe_guide/droplab/plugins/input_setter.md +++ b/doc/development/fe_guide/droplab/plugins/input_setter.md @@ -1,6 +1,6 @@ # InputSetter -`InputSetter` is a plugin that allows for udating DOM out of the scope of droplab when a list item is clicked. +`InputSetter` is a plugin that allows for updating DOM out of the scope of droplab when a list item is clicked. ## Usage From 948afa2ad3717c121fae1d998a72b83f237950b3 Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 14 Jul 2017 08:46:37 +0000 Subject: [PATCH 61/61] Fix spacing in sidebar --- app/assets/stylesheets/pages/builds.scss | 4 ++++ app/views/projects/jobs/_sidebar.html.haml | 8 ++++---- changelogs/unreleased/35035-sidebar-job-spaces.yml | 4 ++++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 changelogs/unreleased/35035-sidebar-job-spaces.yml diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 0393820dee6..b6fc628c02b 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -244,6 +244,10 @@ } } + .block-last { + padding: 16px 0; + } + .trigger-build-variable { color: $code-color; } diff --git a/app/views/projects/jobs/_sidebar.html.haml b/app/views/projects/jobs/_sidebar.html.haml index bddb587ddc6..f2db71e8838 100644 --- a/app/views/projects/jobs/_sidebar.html.haml +++ b/app/views/projects/jobs/_sidebar.html.haml @@ -11,7 +11,7 @@ #js-details-block-vue - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?) - .block{ class: ("block-first" if !@build.coverage) } + .block .title Job artifacts - if @build.artifacts_expired? @@ -37,7 +37,7 @@ Browse - if @build.trigger_request - .build-widget + .build-widget.block %h4.title Trigger @@ -55,7 +55,7 @@ .js-build-variable.trigger-build-variable= key .js-build-value.trigger-build-value= value - .block + %div{ class: (@build.pipeline.stages_count > 1 ? "block" : "block-last") } %p Commit = link_to @build.pipeline.short_sha, project_commit_path(@project, @build.pipeline.sha), class: 'commit-sha link-commit' @@ -69,7 +69,7 @@ - if @build.pipeline.stages_count > 1 .dropdown.build-dropdown - .title + %div %span{ class: "ci-status-icon-#{@build.pipeline.status}" } = ci_icon_for_status(@build.pipeline.status) Pipeline diff --git a/changelogs/unreleased/35035-sidebar-job-spaces.yml b/changelogs/unreleased/35035-sidebar-job-spaces.yml new file mode 100644 index 00000000000..a9a0211efd9 --- /dev/null +++ b/changelogs/unreleased/35035-sidebar-job-spaces.yml @@ -0,0 +1,4 @@ +--- +title: Fix vertical space in job details sidebar +merge_request: +author: