Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Merge pull request #2564 from atom/read-config-without-repo
Browse files Browse the repository at this point in the history
Read and write git configuration without repository
  • Loading branch information
smashwilson authored Nov 20, 2020
2 parents fb57194 + f466251 commit 2c9ffe3
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 184 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ jobs:
- name: install dependencies
shell: bash
run: ${APM} ci
- name: configure git
shell: bash
run: |
git config --global user.name Hubot
git config --global user.email [email protected]
- name: run tests
shell: bash
run: ${ATOM} --test test/
Expand Down Expand Up @@ -79,6 +84,11 @@ jobs:
- name: install dependencies
shell: bash
run: sh -c "${APM} ci"
- name: configure git
shell: bash
run: |
git config --global user.name Hubot
git config --global user.email [email protected]
- name: run tests
shell: bash
run: sh -c "${ATOM} --test test/"
Expand Down
14 changes: 12 additions & 2 deletions lib/controllers/git-tab-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,19 @@ export default class GitTabController extends React.Component {

closeIdentityEditor = () => this.setState({editingIdentity: false})

setUsername = () => this.props.repository.setConfig('user.name', this.usernameBuffer.getText(), {global: true})
setUsername = () => {
const newUsername = this.usernameBuffer.getText();
if (newUsername !== this.props.username) {
this.props.repository.setConfig('user.name', newUsername, {global: true});
}
}

setEmail = () => this.props.repository.setConfig('user.email', this.emailBuffer.getText(), {global: true})
setEmail = () => {
const newEmail = this.emailBuffer.getText();
if (newEmail !== this.props.email) {
this.props.repository.setConfig('user.email', newEmail, {global: true});
}
}

restoreFocus() {
this.refView.map(view => view.setFocus(this.lastFocus));
Expand Down
8 changes: 4 additions & 4 deletions lib/git-shell-out-strategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1007,12 +1007,12 @@ export default class GitShellOutStrategy {
let output;
try {
let args = ['config'];
if (local || atom.inSpecMode()) { args.push('--local'); }
if (local) { args.push('--local'); }
args = args.concat(option);
output = await this.exec(args);
} catch (err) {
if (err.code === 1) {
// No matching config found
if (err.code === 1 || err.code === 128) {
// No matching config found OR --local can only be used inside a git repository
return null;
} else {
throw err;
Expand All @@ -1025,7 +1025,7 @@ export default class GitShellOutStrategy {
setConfig(option, value, {replaceAll, global} = {}) {
let args = ['config'];
if (replaceAll) { args.push('--replace-all'); }
if (global && !atom.inSpecMode()) { args.push('--global'); }
if (global) { args.push('--global'); }
args = args.concat(option, value);
return this.exec(args, {writeOperation: true});
}
Expand Down
164 changes: 164 additions & 0 deletions lib/models/repository-states/cache/keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
class CacheKey {
constructor(primary, groups = []) {
this.primary = primary;
this.groups = groups;
}

getPrimary() {
return this.primary;
}

getGroups() {
return this.groups;
}

removeFromCache(cache, withoutGroup = null) {
cache.removePrimary(this.getPrimary());

const groups = this.getGroups();
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
if (group === withoutGroup) {
continue;
}

cache.removeFromGroup(group, this);
}
}

/* istanbul ignore next */
toString() {
return `CacheKey(${this.primary})`;
}
}

class GroupKey {
constructor(group) {
this.group = group;
}

removeFromCache(cache) {
for (const matchingKey of cache.keysInGroup(this.group)) {
matchingKey.removeFromCache(cache, this.group);
}
}

/* istanbul ignore next */
toString() {
return `GroupKey(${this.group})`;
}
}

export const Keys = {
statusBundle: new CacheKey('status-bundle'),

stagedChanges: new CacheKey('staged-changes'),

filePatch: {
_optKey: ({staged}) => (staged ? 's' : 'u'),

oneWith: (fileName, options) => { // <-- Keys.filePatch
const optKey = Keys.filePatch._optKey(options);
const baseCommit = options.baseCommit || 'head';

const extraGroups = [];
if (options.baseCommit) {
extraGroups.push(`file-patch:base-nonhead:path-${fileName}`);
extraGroups.push('file-patch:base-nonhead');
} else {
extraGroups.push('file-patch:base-head');
}

return new CacheKey(`file-patch:${optKey}:${baseCommit}:${fileName}`, [
'file-patch',
`file-patch:opt-${optKey}`,
`file-patch:opt-${optKey}:path-${fileName}`,
...extraGroups,
]);
},

eachWithFileOpts: (fileNames, opts) => {
const keys = [];
for (let i = 0; i < fileNames.length; i++) {
for (let j = 0; j < opts.length; j++) {
keys.push(new GroupKey(`file-patch:opt-${Keys.filePatch._optKey(opts[j])}:path-${fileNames[i]}`));
}
}
return keys;
},

eachNonHeadWithFiles: fileNames => {
return fileNames.map(fileName => new GroupKey(`file-patch:base-nonhead:path-${fileName}`));
},

allAgainstNonHead: new GroupKey('file-patch:base-nonhead'),

eachWithOpts: (...opts) => opts.map(opt => new GroupKey(`file-patch:opt-${Keys.filePatch._optKey(opt)}`)),

all: new GroupKey('file-patch'),
},

index: {
oneWith: fileName => new CacheKey(`index:${fileName}`, ['index']),

all: new GroupKey('index'),
},

lastCommit: new CacheKey('last-commit'),

recentCommits: new CacheKey('recent-commits'),

authors: new CacheKey('authors'),

branches: new CacheKey('branches'),

headDescription: new CacheKey('head-description'),

remotes: new CacheKey('remotes'),

config: {
_optKey: options => (options.local ? 'l' : ''),

oneWith: (setting, options) => {
const optKey = Keys.config._optKey(options);
return new CacheKey(`config:${optKey}:${setting}`, ['config', `config:${optKey}`]);
},

eachWithSetting: setting => [
Keys.config.oneWith(setting, {local: true}),
Keys.config.oneWith(setting, {local: false}),
],

all: new GroupKey('config'),
},

blob: {
oneWith: sha => new CacheKey(`blob:${sha}`, ['blob']),
},

// Common collections of keys and patterns for use with invalidate().

workdirOperationKeys: fileNames => [
Keys.statusBundle,
...Keys.filePatch.eachWithFileOpts(fileNames, [{staged: false}]),
],

cacheOperationKeys: fileNames => [
...Keys.workdirOperationKeys(fileNames),
...Keys.filePatch.eachWithFileOpts(fileNames, [{staged: true}]),
...fileNames.map(Keys.index.oneWith),
Keys.stagedChanges,
],

headOperationKeys: () => [
Keys.headDescription,
Keys.branches,
...Keys.filePatch.eachWithOpts({staged: true}),
Keys.filePatch.allAgainstNonHead,
Keys.stagedChanges,
Keys.lastCommit,
Keys.recentCommits,
Keys.authors,
Keys.statusBundle,
],
};
Loading

0 comments on commit 2c9ffe3

Please sign in to comment.